Juan Juan - 27 days ago 11
Javascript Question

mongoose.js: How do I remove a property from a subarray of references while using populate and use one of the subarray field as a filter as well?

I have the following code in node js using mongoose package.

1)How do I remove the field total within the foundations array on the response if I'm using the populate method??. Cause that array is formed by references to another collection.

2) How do I use the "campaigns.state" field to filter only the campaigns that has "ACTIVE" as the state?

The definition:

FOUNDATION model

var mongoose=require('mongoose');
var Schema = mongoose.Schema;

var foundation = new Schema({

twitter_account:{type: String, required: true, unique: true},

name:{type: String, required: true, unique: true},

pic_path: {type: String, required: true},

doc_path: {type: String, required: true},

campaigns: [{type: Schema.ObjectId, ref: 'Campaign'}]
},{
timestamps: true
});

module.exports = mongoose.model('Foundation', foundation);


on the Campaigns model I have the Foundations field which is an array of references to foundations and I want to cut it out on the response to avoid redundancy

var campaign = new Schema({

.............

foundations: [{type: Schema.ObjectId, ref: 'Foundation'}],

......................
}


HERE IS THE ROUTE OF THE API WHERE I RETRIEVE THE DATA

var express = require('express');
var router = express.Router();
var Foundation=require('../models/Foundation');
var mongoose= require('mongoose');
var Promise = require("bluebird");
var _ = require('lodash');


//get all Foundations
router.get('/get/all', function(req, res, next) {

var results=Foundation.find({},{twitter_account:1,name:1,campaigns:1})

.populate('campaigns').exec(function (err, foundation) {
if (err) return handleError(err);
console.log(foundation);
res.send(foundation);
});

});

module.exports = router;


Here is the response:

[
{
"_id": "58229b253e1ad628e1ed975e",
"twitter_account": "@YYYYYYYYYYYY",
"name": "YYYYYYYYYYYY",
"campaigns": [
{
"_id": "5822a9444aea133044b6eb84",
"updatedAt": "2016-11-09T04:42:44.922Z",
"createdAt": "2016-11-09T04:42:44.922Z",
"total": 0,
"state": "ACTIVE",
"__v": 0,
"end_date": null,
"foundations": [
"58229b253e1ad628e1ed975e",
"58229b253e1ad628e1ed975f"
]
},
{
"_id": "5822a9444aea133044b6eb85",
"updatedAt": "2016-11-09T04:42:44.925Z",
"createdAt": "2016-11-09T04:42:44.925Z",
"remaining_ammount_to_goal": 500000,
"total": 0,
"state": "ACTIVE",
"__v": 0,
"end_date": null,
"foundations": [
"58229b253e1ad628e1ed975e"
]
}
]
},
{
"_id": "58229b253e1ad628e1ed975f",
"twitter_account": "@XXXXXXXXXXX",
"name": "XXXXXXXXX",
"campaigns": [
{
"_id": "5822a9444aea133044b6eb85",
"updatedAt": "2016-11-09T04:42:44.925Z",
"createdAt": "2016-11-09T04:42:44.925Z",
"total": 0,
"state": "ACTIVE",
"__v": 0,
"end_date": null,
"foundations": [
"58229b253e1ad628e1ed975e"
]
}
]


Desired response( just want to drop foundation array field within campaigns objects):

[
{
"_id": "58229b253e1ad628e1ed975e",
"twitter_account": "@YYYYYYYYYYYY",
"name": "YYYYYYYYYYYY",
"campaigns": [
{
"_id": "5822a9444aea133044b6eb84",
"updatedAt": "2016-11-09T04:42:44.922Z",
"createdAt": "2016-11-09T04:42:44.922Z",
"total": 0,
"state": "ACTIVE",
"__v": 0,
"end_date": null
},
{
"_id": "5822a9444aea133044b6eb85",
"updatedAt": "2016-11-09T04:42:44.925Z",
"createdAt": "2016-11-09T04:42:44.925Z",
"remaining_ammount_to_goal": 500000,
"total": 0,
"state": "ACTIVE",
"__v": 0,
"end_date": null
}
]
},
{
"_id": "58229b253e1ad628e1ed975f",
"twitter_account": "@XXXXXXXXXXX",
"name": "XXXXXXXXX",
"campaigns": [
{
"_id": "5822a9444aea133044b6eb85",
"updatedAt": "2016-11-09T04:42:44.925Z",
"createdAt": "2016-11-09T04:42:44.925Z",
"total": 0,
"state": "ACTIVE",
"__v": 0,
"end_date": null
}
]


Any ideas?. Thank you very much!!!

EDIT: For future reference, to filter the objects that has state="Active" on the "Campaigns"JSONArray using populate I achieved that using:
var results=Foundation.find({},{twitter_account:1,name:1,campaigns:1})

.populate({path : 'campaigns' ,select :'-foundations', match:{state:'ACTIVE'}}).exec(function (err, foundation) {
if (err) return handleError(err);
console.log(foundation);
res.send(foundation);
});

Answer

You can use populate with select

       var results=Foundation.find({},{twitter_account:1,name:1,campaigns:1})
          .populate({path : 'campaigns' ,select :'-foundations'})
          .exec(function (err, foundation) {
                if (err) return handleError(err);
                console.log(foundation);
                res.send(foundation);
        });

Just go through the mongoose documentation http://mongoosejs.com/docs/populate.html