Reputation: 2981
I'm struggling to find the right syntax for my query.
I have the following schema
var Person = mongoose.Schema({
name: String,
cars: [{type: Schema.Types.ObjectId, ref: 'Car'}] -- Note this is an array
});
I want to write a query that effectively tells me all the people that own a red car.
I think I want something like:
Person.find().populate('cars').match({colour:red}).exec(function(err, models) {....
But I can't find any documentation to back this up. Any tips appreciated.
EDIT:
This code is getting close, but still no there
Person.find()
.populate({path: 'cars', match: {colour: "red"}})
.exec(function (err, Persons) {
The reason being, it returns all 'Person' records and only populates the 'cars' array for those it matches in the populate function. As a result I get lots of Person.cars.length === 0 in there.
If I add a modification to the find:
Person.find()
.populate({path: 'cars', match: {colour: "red"}})
.where({'cars' : {$not: {$size: 0}}}
.exec(function (err, Persons) {
This also has no affect; I'm assuming the where runs before the populate. Breaking the query up into separate lines has no affect either.
Upvotes: 0
Views: 49
Reputation: 312129
It's typically more efficient to flip these type of queries around and first find the _ids of all the red cars and then find the people with those cars:
Car.find({colour: 'red'}, function(err, cars) {
var carIds = cars.map(function(car) {
return car._id;
});
Person.find({cars: {$in: carIds}}, function(err, persons) {...});
});
Upvotes: 1
Reputation: 20445
try this , break it up in this manner
var q = Person.find();
q.populate('cars').match({color:red}).exec(function(err, models) {....}
or this , with thee same effect
var q = Person.find();
q.populate({path: 'cars', match: { color:red}}).exec(function(err, models) {....}
then you have to filter for whether car is present or not
like
.exec(function(err, models){
models= docs.filter(function(model){
return doc.cars.length;
})
// do stuff with models
});
Upvotes: 1