To populate nested array in Mongoose, we can use the populate method. Project. find(query) . populate({ path: 'pages', populate: { path: 'components', model: 'Component' } }) .
Mongoose has a more powerful alternative called populate() , which lets you reference documents in other collections. Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s).
Mongoose also supports populating virtuals. A populated virtual contains documents from another collection. To define a populated virtual, you need to specify: The ref option, which tells Mongoose which model to populate documents from. The localField and foreignField options.
Mongoose uses two queries to fulfill the request. The a collection is queried to get the docs that match the main query, and then the j collection is queried to populate the d field in the docs.
Mongoose 4.5 support this
Project.find(query)
.populate({
path: 'pages',
populate: {
path: 'components',
model: 'Component'
}
})
.exec(function(err, docs) {});
And you can join more than one deep level.
Edit 03/17/2021: This is the library's implementation, what it do behind the scene is make another query to fetch thing for you and then join in memory. Although this work but we really should not rely on. It will make your db design look like SQL tables. This is costly operation and does not scale well. Please try to design your document so that it reduce join.
That works for me:
Project.find(query)
.lean()
.populate({ path: 'pages' })
.exec(function(err, docs) {
var options = {
path: 'pages.components',
model: 'Component'
};
if (err) return res.json(500);
Project.populate(docs, options, function (err, projects) {
res.json(projects);
});
});
Documentation: Model.populate
As others have noted, Mongoose 4
supports this. It is very important to note that you can recurse deeper than one level too, if needed—though it is not noted in the docs:
Project.findOne({name: req.query.name})
.populate({
path: 'threads',
populate: {
path: 'messages',
model: 'Message',
populate: {
path: 'user',
model: 'User'
}
}
})
You can populate multiple nested documents like this.
Project.find(query)
.populate({
path: 'pages',
populate: [{
path: 'components',
model: 'Component'
},{
path: 'AnotherRef',
model: 'AnotherRef',
select: 'firstname lastname'
}]
})
.exec(function(err, docs) {});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With