Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose populate sub-sub document

I have this setup in my MongoDB

Items:

title: String comments: [] // of objectId's 

Comments:

user: ObjectId() item: ObjectId() comment: String 

Here's my Mongoose schema:

itemSchema = mongoose.Schema({     title: String,     comments: [{ type: Schema.Types.ObjectId, ref: 'comments' }], });  Item = mongoose.model('items', itemSchema);  commentSchema = mongoose.Schema({     comment: String,     user: { type: Schema.Types.ObjectId, ref: 'users' }, });  Comment = mongoose.model('comments', commentSchema); 

This is where I get my items along with the comments:

Item.find({}).populate('comments').exec(function(err, data){     if (err) return handleError(err);     res.json(data); }); 

How do I populate the comments array with it's respective user? Since each comment has a user ObjectId()?

like image 677
iamjonesy Avatar asked Jun 25 '14 17:06

iamjonesy


People also ask

How does populate work in Mongoose?

Mongoose Populate() Method. In MongoDB, Population is the process of replacing the specified path in the document of one collection with the actual document from the other collection.


2 Answers

One more way (easier) to do this:

Item    .find({})    .populate({  	path:     'comments',			  	populate: { path:  'user',  		    model: 'users' }    })    .exec(function(err, data){      if (err) return handleError(err);      res.json(data);  });
like image 154
Antenka Avatar answered Sep 21 '22 12:09

Antenka


As a complete example calling populate on the result objects:

Item.find({}).populate("comments").exec(function(err,data) {     if (err) return handleError(err);      async.forEach(data,function(item,callback) {         User.populate(item.comments,{ "path": "user" },function(err,output) {             if (err) throw err; // or do something              callback();         });     }, function(err) {         res.json(data);     });  }); 

The call to .populate() in the form invoked from the model takes either a document or an array as it's first argument. So you loop through the returned results for each item and call populate this way on each "comments" array. The "path" tells the function what it is matching.

This is done using the "async" version of forEach so it is non-blocking, but generally after all the manipulation all of the items in the response are not only populated with comments but the comments themselves have the related "user" details.

like image 40
Neil Lunn Avatar answered Sep 21 '22 12:09

Neil Lunn