in a Node.js
App with Mongoose(Mongodb)
, With this code i fetch users and their books:
Users.find({user_id: req.user.id}).populate('books').exec(..);
Right now i want to fetch users that has an special book. i do like this:
Users.find({user_id: req.user.id}).populate('books',null,{bookname:"harry potter"}).exec(..);
But it doesn't work. With this, my code fetches users with their books of null
value and if that condition matches, return them instead of null. In fact most of my users has null
value for books. but what i want is that if that condioton in populate section is not matches, do not return that user in result array at all!
What i have to do? i have to do another query or something on results for what i need?
in a Node.js
App with Mongoose(Mongodb)
, With this code i fetch users and their books:
Users.find({user_id: req.user.id}).populate('books').exec(..);
Right now i want to fetch users that has an special book. i do like this:
Users.find({user_id: req.user.id}).populate('books',null,{bookname:"harry potter"}).exec(..);
But it doesn't work. With this, my code fetches users with their books of null
value and if that condition matches, return them instead of null. In fact most of my users has null
value for books. but what i want is that if that condioton in populate section is not matches, do not return that user in result array at all!
What i have to do? i have to do another query or something on results for what i need?
Share Improve this question asked Sep 6, 2015 at 13:44 FcoderFcoder 9,22618 gold badges68 silver badges103 bronze badges2 Answers
Reset to default 3All I can think here is that you are calling it wrong. You do not really show much context here other than that your .populate()
parameters do not look correct.
Here is a correct listing as a reproducible example:
var async = require('async'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
var thingSchema = new Schema({
_id: Number,
name: String
},{ _id: false });
var parentSchema = new Schema({
name: String,
things: [{ type: Number, ref: 'Thing' }]
});
var Thing = mongoose.model( 'Thing', thingSchema ),
Parent = mongoose.model( 'Parent', parentSchema );
mongoose.connect('mongodb://localhost/thingtest');
var things = { "one": 1, "two": 2, "three": 3 };
async.series(
[
function(callback) {
async.each([Thing,Parent],function(model,callback) {
model.remove({},callback);
},callback);
},
function(callback) {
var parentObj = new Parent({ "name": "me" });
async.each(
Object.keys(things).map(function(key) {
return { "name": key, "_id": things[key] }
}),
function(thing,callback) {
var mything = new Thing(thing);
parentObj.things.push(thing._id)
mything.save(callback)
},
function(err) {
if (err) callback(err);
parentObj.save(callback);
}
);
},
function(callback) {
console.log("filtered");
var options = {
path: 'things',
match: { "name": { "$in": ['two','three'] } }
};
Parent.find().populate(options).exec(function(err,docs) {
if (err) callback(err);
console.log(docs);
callback();
});
},
function(callback) {
console.log('unfiltered');
Parent.find().populate('things').exec(function(err,docs) {
if (err) callback(err);
console.log(docs);
callback();
})
}
],
function(err) {
if (err) throw err;
mongoose.disconnect();
}
);
Which will consistently give results like this:
filtered
[ { _id: 55ec4c79f30f550939227dfb,
name: 'me',
__v: 0,
things:
[ { _id: 2, name: 'two', __v: 0 },
{ _id: 3, name: 'three', __v: 0 } ] } ]
unfiltered
[ { _id: 55ec4c79f30f550939227dfb,
name: 'me',
__v: 0,
things:
[ { _id: 1, name: 'one', __v: 0 },
{ _id: 2, name: 'two', __v: 0 },
{ _id: 3, name: 'three', __v: 0 } ] } ]
So take a good look at your data and your calls. The .populate()
call needs to match the "path" and then also provide a "match" to query the documents that are to be populated.
Use elemMatch:
var title = 'Harry Potter';
Users.find({books: {$elemMatch: {name: title}})
.exec(processResults);