Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Populate nested array in mongoose

People also ask

How do you populate a nested array object in MongoDB?

To populate nested array in Mongoose, we can use the populate method. Project. find(query) . populate({ path: 'pages', populate: { path: 'components', model: 'Component' } }) .

What is the use of populate in mongoose?

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).

What is virtual populate in mongoose?

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.

How does mongoose populate work under the hood?

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) {});