Filling a nested array in mongoose

How can I fill in the "components" in an example document:

{ "__v": 1, "_id": "5252875356f64d6d28000001", "pages": [ { "__v": 1, "_id": "5252875a56f64d6d28000002", "page": { "components": [ "525287a01877a68528000001" ] } } ], "author": "Book Author", "title": "Book Title" } 

This is my JS where I get the Mongoose document:

  Project.findById(id).populate('pages').exec(function(err, project) { res.json(project); }); 
+76
mongodb mongoose
Oct 07 '13 at 10:32 on
source share
8 answers

Mongoose 4.5 supports this

 Project.find(query) .populate({ path: 'pages', populate: { path: 'components', model: 'Component' } }) .exec(function(err, docs) {}); 
+152
Dec 23 '15 at 22:58
source share

This 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

+98
Oct 07 '13 at 14:40
source share

As already noted, Mongoose 4 supports this. It is very important to note that you can go deeper than one level, if necessary, although this is not indicated in the documentation:

 Project.findOne({name: req.query.name}) .populate({ path: 'threads', populate: { path: 'messages', model: 'Message', populate: { path: 'user', model: 'User' } } }) 
+20
Apr 16 '16 at 4:02
source share

You can fill out several attached 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) {}); 
+8
Apr 29 '18 at 8:22
source share

I found this very useful when creating feathersjs before hook to populate the ratio 2 ref level deep. Mongoose models just have

 tables = new Schema({ .. tableTypesB: { type: Schema.Types.ObjectId, ref: 'tableTypesB' }, .. } tableTypesB = new Schema({ .. tableType: { type: Schema.Types.ObjectId, ref: 'tableTypes' }, .. } 

then in feathersjs before hook:

 module.exports = function(options = {}) { return function populateTables(hook) { hook.params.query.$populate = { path: 'tableTypesB', populate: { path: 'tableType' } } return Promise.resolve(hook) } } 

So simple compared to some other methods that I tried to achieve.

+2
Sep 21 '17 at 11:59 on
source share

You can do this using the $lookup aggregation, and probably the best way, as currently filling is dying out from mongo

 Project.aggregate([ { "$match": { "_id": mongoose.Types.ObjectId(id) } }, { "$lookup": { "from": Pages.collection.name, "let": { "pages": "$pages" }, "pipeline": [ { "$match": { "$expr": { "$in": [ "$_id", "$$pages" ] } } }, { "$lookup": { "from": Component.collection.name, "let": { "components": "$components" }, "pipeline": [ { "$match": { "$expr": { "$in": [ "$_id", "$$components" ] } } }, ], "as": "components" }}, ], "as": "pages" }} ]) 
+1
Jul 02 '18 at 5:07
source share

I found this question in another question that was specific to KeystoneJS but was marked as duplicate. If someone here can look for Keystone's answer, I did my in-depth query on Keystone.

Mongoose two-tier population using KeystoneJs [duplicates]

 exports.getStoreWithId = function (req, res) { Store.model .find() .populate({ path: 'productTags productCategories', populate: { path: 'tags', }, }) .where('updateId', req.params.id) .exec(function (err, item) { if (err) return res.apiError('database error', err); // possibly more than one res.apiResponse({ store: item, }); }); }; 
0
Nov 14 '18 at 22:32
source share

Delete document link

 if (err) { return res.json(500); } Project.populate(docs, options, function (err, projects) { res.json(projects); }); 

It worked for me.

 if (err) { return res.json(500); } Project.populate(options, function (err, projects) { res.json(projects); }); 
-2
Mar 26 '15 at 15:47
source share



All Articles