I am trying to populate my model which looks like:
var Org = new mongoose.Schema({
_id: {type: String, unique:true}, //this will be the org code
name: String,
level: String,
children: [{type: String, ref: 'Org'}]
});
//Orgs have children orgs, which themselves can have children orgs at N levels
Given an Org, I would like to populate its children, and its childrens children and so on. I can accomplish this for N = 2 levels as such:
req.Model.findOne({_id: id}).populate('children').exec(function(err, doc){
if (err){
return next(err);
}
req.Model.populate(doc, {path: 'children.children'}, function(err, doc){
if(err){
return next(err);
}
return res.json(doc);
});
});
For hours now I have been trying to accomplish the above using promises, even at N=2. I think that for N = * levels, It would be cleaner to do so with promises which mongoose has a built in implementation of.
req.Model.findOne({_id: id}).populate('children').exec()
.then(function (doc){
if(!treeView) {
return doc;
}
return req.Model.populate(doc, {path: 'children.children'});
})
.then(function (doc){
return res.json(doc);
},function(err){
return next(err);
});
// treeView is a query string that lets me know that I need to populate the refs
I think it should be working as follows:
I am getting this Error:
{
"status": "error",
"serverTimestamp": "2014-07-24T18:23:02.974Z",
"message": "\"function\" == \"undefined\""
}
I know it gets to the second then()'s error handler, because I have logged out to the console to verify, but I cannot figure out why this is happening. Once I can get this to work, I will try to make it work for N=* levels, which I imagine would involve creating more promises recursively. I have seen many questions here related, but not exactly what I needed.
Any help is greatly appreciated.
I was able to make nested subdocument populate work in MongooseJS v4.1 using the Mongoose promise returned from the mongoose model. No need to use another promise library.
var fuelOrderId = req.params.fuelOrderId;
fuelOrderModel.findById(fuelOrderId).populate('aircraftId')
.then(function(order){
return fuelOrderModel.populate(order,
{path: 'aircraftId.aircraftContacts',
model: 'aircraftContactModel'});
})
.then(function(result){
res.json({
fuelOrder: result,
status: 1
});
},function(err){
console.error(err);
res.json({err: err, status: 0});
})
Edit consider using .catch()
instead of a second function for errors. mpromise now supports .catch()
.
Seems like a found a solution for now.
Q.ninvoke(doc, 'populate',{path: children.children})
.then(function(doc){
return res.json(doc);
},function(err) {
return next(err);
});
What is weird to me is that I need to use mongooses Document.populate and not Model.populate(doc..) which according the the documentation should behave pretty similarly with the exception that one returns a promise. This is one reason I had to use the Q promise api, since Document.populate doesnt return a promise like Model.populate does. I could not get Model.populate to work without a regular node style callback but this solution does what I need. As for N=* levels, I just recursively call Q.ninvoke as many times as I need, extending the path and I can populate as many levels deep as I want.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.