Assuming that I have 3 models :
// Parent
const ParentSchema = new Schema({
child: {
type: ObjectId,
ref: 'Child'
},
...
});
// Child
const ChildSchema = new Schema({
subChild: {
type: ObjectId,
ref: 'SubChild'
},
...
});
// SubChild
const SubChildSchema = new Schema({
name: String,
...
});
I'm using findOne
on Parent
, and I'd like to use populate
on Child
, but also on SubChild
:
Parent.findOne(options)
.populate('child', 'subChild')
// Trying to add another populate on subChild property like : .populate('<above_subChild>', 'name')
.select('child')
.exec(function (err, parent) {
callback(err, parent.toJSON());
})
;
Is there a way to do that with populate
?
Currently, parent.toJSON()
returns :
{
// Parent _id
_id: XXX,
child: {
_id: XXX,
subChild: <subChild_ObjectID>
}
}
And below is the result I'd like to have by adding another populate
on subChild
property is :
{
// Parent _id
_id: XXX,
child: {
_id: XXX,
subChild: {
_id: XXX,
name: XXX
}
}
}
This also will work :
Parent.findOne(options)
.select('child')
.populate('child.subChild')
.exec(function(err, parent) {
callback(err, parent.toJSON());
});
Referring to the documentation for populate
, the query would need to be structured as follows for populating multiple levels:
Parent.findOne(options)
.populate({
path: 'child',
populate: {
path: 'subChild'
}
})
.select('child')
.exec(function(err, parent) {
callback(err, parent.toJSON());
});
One thing to note with using mongoose's populate
method is that every population requires a separate query. So in this case, while the implementation uses one explicit findOne
method, mongoose is actually executing three queries serially.
This would be roughly equivalent to (slightly pseudo-coding):
Parent.findOne().exec().then((parent) => ([
parent,
Child.findById(parent.child).exec()
])).then(([parent, child]) => ([
parent,
child,
SubChild.findById(child.subChild).exec()
])).then(([parent, child, subChild]) => {
child.subChild = subChild;
parent.child = child;
return parent;
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.