【问题标题】:Nested mongoose populate with promises嵌套的猫鼬填充了承诺
【发布时间】:2014-09-16 12:48:34
【问题描述】:

我正在尝试填充我的模型,如下所示:

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

给定一个组织,我想填充它的孩子,以及它的孩子的孩子等等。我可以为 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);
        });
    });

几个小时以来,我一直在尝试使用 Promise 完成上述任务,即使在 N=2 时也是如此。我认为对于 N = * 级别,使用 mongoose 内置实现的 Promise 这样做会更干净。

        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

我认为它应该如下工作:

  1. exec() 返回一个 promise,我在第一次调用 then() 时开始处理它
  2. 如果 treeView 为假,我返回 doc,这被视为原始承诺的解决方案,因此第二个 then() 处理程序被调用。这确实发生了。
  3. 如果 treeView 为真,对 Model.populate 的调用将返回另一个承诺,该承诺也将在第二次调用 then() 时得到处理。

我收到此错误:

{
   "status": "error",
   "serverTimestamp": "2014-07-24T18:23:02.974Z",
   "message": "\"function\" == \"undefined\""
}

我知道它会到达第二个 then() 的错误处理程序,因为我已经注销到控制台进行验证,但我无法弄清楚为什么会发生这种情况。一旦我可以让它工作,我将尝试让它在 N=* 级别上工作,我想这将涉及递归地创建更多的 Promise。我在这里看到了很多相关的问题,但不完全是我需要的。

非常感谢任何帮助。

【问题讨论】:

    标签: javascript node.js mongoose


    【解决方案1】:

    我能够使用从 mongoose 模型返回的 Mongoose 承诺在 MongooseJS v4.1 中使嵌套子文档填充工作。无需使用其他 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});
    })
    

    编辑考虑使用.catch() 而不是第二个函数来解决错误。 mpromise 现在支持.catch()

    【讨论】:

      【解决方案2】:

      现在似乎找到了解决方案。

      Q.ninvoke(doc, 'populate',{path: children.children})
      .then(function(doc){
          return res.json(doc);
      },function(err) {
          return next(err);
      });
      

      对我来说奇怪的是我需要使用猫鼬 Document.populate 而不是 Model.populate(doc..) 根据文档应该表现得非常相似,除了一个返回一个承诺。这是我不得不使用 Q Promise api 的原因之一,因为 Document.populate 不会像 Model.populate 那样返回 Promise。如果没有常规的节点样式回调,我无法让 Model.populate 工作,但这个解决方案可以满足我的需要。至于 N=* 级别,我只是根据需要递归调用 Q.ninvoke 多次,扩展路径,我可以根据需要填充任意深度的级别。

      【讨论】:

      • 似乎这是使 document#populate 适合承诺链的唯一方法。谢谢。
      猜你喜欢
      • 2014-03-27
      • 2015-04-01
      • 2015-02-09
      • 2021-11-07
      • 2014-07-28
      • 2021-12-25
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多