【问题标题】:Mongoose: insert one collection depenting on an other with promisesMongoose:插入一个依赖于另一个集合的集合
【发布时间】:2016-08-25 01:40:22
【问题描述】:

我需要在两个集合中插入记录。第二个集合存储第一个集合的记录 ID。这是一个 1:m (first:second) 的情况。触发器是第二个集合:

  1. 如果需要存储第二个集合的记录
  2. 检查第一个集合中是否已有拟合记录
  3. 如果不是:则在第一个集合中保存一个
  4. 存储第二个集合
  5. 将第一个集合的记录id保存到第二个集合中

以下示例似乎完成了这些步骤。但我的承诺只有一半。 如何以更好的“承诺”方式做到这一点?

saveObjects(name: String, objects: Array<IObject>){

        var promise = FirstModel.findOne({Name : name}).exec();
        promise.then(function(res1){
            if (!res1){
                var la = new FirstModel();
                la.Name = name;
                la.save(function(err){
                    if (err) throw err;
                })
            }
        }).error(function(err){
            throw err;
        })

        objects.forEach(function(obj) {
            FirstModel.findOne({Name : name},'_id',function(err, res2){
                if (err) throw err;

                var vo = new SecondModel();
                vo.Name = name;
                vo.FistID = res2._id;

                vo.save(function(err){
                    if (err) throw err;
                });
            });
        });

}

【问题讨论】:

    标签: mongodb mongoose promise


    【解决方案1】:

    我在这里假设您使用的是 bluebird 或其他等效的 Promise 设置。

    var Promise = require('bluebird');
    saveObjects(name: String, objects: Array < IObject > ) {
    
        // Get the first model
        return FirstModel
            .findOne({
                Name: name
            })
            .exec()
            .then(function (res1) {
                if (!res1) {
                    var la = new FirstModel();
                    la.Name = name;
                    return la.save() // We return the save operation on the model, save() returns a promise
                }
    
                // We just return the model normally so it passes down the chain.
                return res1;
            })
            .then(function (res1) {
                // Here we use Promise.all() method on bluebird which accepts an Array
                // of promises, we create a promise from the objects array by using Array.map() which
                // goes through every object in the array and creates a new array. 
                return Promise
                    .all(objects.map(function (obj) {
                        // We go through each object in objects and create a new 
                        // model and return the save() method of each model, this
                        // creates a array of promises which are resolved when each
                        // all model has been saved.
                        var vo = new SecondModel();
                        vo.Name = name;
                        vo.FistID = res1._id;
    
                        return vo.save();
                    }));
            })
            .then(function (models) {
                // here we have all the models we just saved in an array called models,
                // do what you want with it.
            })
            .error(function (err) {
                throw err;
            })
    }
    

    有关更多信息,请参阅有关 Array.map() herePromise.all() here 的文档

    【讨论】:

    • 但是对 FirstModel 的引用 vo.FistID = res1._id; 在上面的示例中会引发错误,因为 res1._id 不在 .then 部分的范围内。这就是为什么我在这个地方进一步阅读了 FirstModel 的原因。有没有更好的方法来做到这一点?
    • res1 在第二个 then() 中定义,所以它应该可以正常工作。我们将 res1 从第一个 then() 传递给第二个。如果您收到错误,请将其粘贴到此处,以便我查看它是什么。如果你直接复制/粘贴,你应该知道我刚刚修复了一个小语法错误,所以你应该再试一次。
    • 我得到的错误是error TS2339: Property '_id' does not exist on type '{}'.这对我来说似乎是第二部分不知道res1。
    • 对我来说看起来像是一个打字稿错误,我对打字稿没有什么经验,但我的猜测是你需要在函数中为 FirstModel 定义打字稿,类似于 .then(function(res1: FirstModel) { ... })
    • 非常感谢。是的,这似乎是一个 TS 问题。虽然我无法通过添加类型来解决它。我做了一个额外的阅读链。但是在一个简单的 js 环境中,我刚刚复制了你的代码,我调用 commit 它工作 - 所以再次感谢。
    猜你喜欢
    • 2015-04-09
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 2018-12-11
    • 2021-02-11
    • 1970-01-01
    • 2022-01-19
    • 2016-09-22
    相关资源
    最近更新 更多