I am having the following scenario and I need to understand better how population works: I have 3 schema as below. I need to filter child schema based on grandparent property name. I created a populate on pre find but looks like the populate does not help to filter based on property but only on object ID. The controller code is like below:
filter= {childname: req.params.childname, 'child.parent.grandparent.grandparentname': req.params.grandparent};
const result = await Child.find(filter)
const childSchema = new mongoose.Schema(
{
childname: {
type: String,
},
parent:{
type:mongoose.Schema.ObjectId,
ref: 'Parent',
required: [true, "Parent missing"],
// select: false
}
},
{ timestamps: true },
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
childSchema.pre(/^find/, function(next) {
this.populate
(
{path: 'parent',select: '-__v',
populate: [
{ path: 'grandparent', select: 'grandparentname' }
]
});
next();
});
const Child = mongoose.model( 'Child', childSchema);
module.exports = Child;
const parentSchema = new mongoose.Schema(
{
parentname: {
type: String,
},
grandparent:{
type:mongoose.Schema.ObjectId,
ref: 'grandparent',
required: [true, "Grand parent missing"],
// select: false
},
},
{ timestamps: true },
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
const Parent = mongoose.model( 'Parent', parentSchema);
module.exports = Parent;
const grandparentSchema = new mongoose.Schema(
{
grandparentname: {
type: String,
}
},
{ timestamps: true },
{
toJSON: { virtuals: true },
toObject: { virtuals: true }
}
);
const Grandparent = mongoose.model( 'Grandparent', grandparentSchema);
module.exports = Grandparent;
CodePudding user response:
I have the answer!
Firstly - remove your Childschema.pre('^/find...
and use next code:
const result = await Child.aggregate([{
$match: {
childname: YOUR_CHILDNAME_VARIABLE,
}
}, {
$lookup: {
from: 'parents',
localField: 'parent',
foreignField: '_id',
as: 'parent',
pipeline: [
{
"$lookup": {
"from": "grandparents",
localField: "grandparent",
foreignField: "_id",
"as": "grandparent"
},
}, {
$unwind: '$grandparent'
},
]
}
}, {
$unwind: '$parent'
}, {
"$match": {"parent.grandparent.grandparentname": YOUR_GRANDPARENTNAME_VAIRABLE}
}]);
I tried to do it using populate but haven't had a result :( so, I'v found the solution with aggregate, it works!