简体   繁体   English

嵌套的猫鼬充满了希望

[英]Nested mongoose populate with promises

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: 我可以为N = 2个级别完成此操作,如下所示:

     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. 几个小时以来,即使在N = 2的情况下,我仍在尝试使用Promise来完成上述任务。 I think that for N = * levels, It would be cleaner to do so with promises which mongoose has a built in implementation of. 我认为对于N = *级别,使用猫鼬具有内置实现的承诺会更清洁。

        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: 我认为它应该如下工作:

  1. exec() returns a promise, which I start to handle on the first call to then() exec()返回一个promise,我在对then()的第一次调用时就开始处理
  2. if treeView is false, I return doc, which is seen as a resolution of the original promise and therefore the second then() handler gets called. 如果treeView为false,我返回doc,这被视为原始诺言的解决方案,因此调用了第二个then()处理函数。 This does happen. 这确实发生了。
  3. if treeView is true, the call to Model.populate returns another promise, which will also get handled in the second call to then(). 如果treeView为true,则对Model.populate的调用将返回另一个Promise,第二个对then()的调用也将处理该Promise。

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. 我知道它到达第二个then()的错误处理程序,因为我已经注销到控制台进行验证,但是我无法弄清楚为什么会这样。 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. 一旦使它生效,我将尝试使其适用于N = *级,我想这将涉及递归地创建更多的Promise。 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. 我能够使用Mongoose模型返回的Mongoose许诺在MongooseJS v4.1中使嵌套的子文档填充工作。 No need to use another promise library. 无需使用其他Promise库。

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. 编辑考虑使用.catch()代替错误的第二个函数。 mpromise now supports .catch() . mpromise现在支持.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. 对我来说,很奇怪的是,我需要使用猫鼬Document.populate而不是Model.populate(doc ..),根据文档的表现,猫鼬应该表现得非常相似,不同之处在于它返回了一个promise。 This is one reason I had to use the Q promise api, since Document.populate doesnt return a promise like Model.populate does. 这是我不得不使用Q Promise API的原因之一,因为Document.populate不像Model.populate那样返回Promise。 I could not get Model.populate to work without a regular node style callback but this solution does what I need. 没有常规的节点样式回调,我无法使Model.populate工作,但是此解决方案可以满足我的需求。 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. 至于N = *级别,我只是根据需要递归调用Q.ninvoke多次,从而扩展了路径,并且可以根据需要填充任意数量的级别。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM