Preencher matriz aninhada em mangusto

Como posso preencher “componentes” no documento de exemplo:

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

Este é o meu JS, onde eu recebo o documento por Mongoose:

  Project.findById(id).populate('pages').exec(function(err, project) { res.json(project); }); 

Mangusto 4.5 apoiar este

 Project.find(query) .populate({ path: 'pages', populate: { path: 'components', model: 'Component' } }) .exec(function(err, docs) {}); 

Isso funciona para mim:

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

Documentação: Model.populate

Como outros notaram, o Mongoose 4 suporta isso. É muito importante notar que você também pode recorrer a mais de um nível, se necessário – embora não seja observado nos documentos:

 Project.findOne({name: req.query.name}) .populate({ path: 'threads', populate: { path: 'messages' , model: 'Message' , populate: { path: 'user' , model: 'User' } } }) 

Achei muito útil criar um featherjs antes do hook para preencher uma relação profunda de nível 2 ref. Os modelos de mangusto simplesmente têm

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

então em penas antes de enganchar:

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

Tão simples em comparação com alguns outros methods que eu estava tentando conseguir isso.

Você pode preencher vários documentos nesteds como este.

  Project.find(query) .populate({ path: 'pages', populate: [{ path: 'components', model: 'Component' },{ path: 'AnotherRef', model: 'AnotherRef', select: 'firstname lastname' }] }) .exec(function(err, docs) {}); 

Você pode fazer isso usando a agregação $lookup

 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" }} ]) 

Remover referência de documentos

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

Isso funcionou para mim.

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