【问题标题】:Creating and updating documents synchronously with mongoose使用 mongoose 同步创建和更新文档
【发布时间】:2016-01-13 22:39:01
【问题描述】:

我想知道在 Node.js 和 mongoose 中实现以下情况的最佳方法是什么:

我有一个包含用户的集合和一个包含组的集合。我希望用户能够创建新组并向他们添加人员(非常类似于创建新 whatsapp 组的人)。我对用户和组文档使用以下模式:

var userSchema = mongoose.Schema({ 
    email: String, 
    hashed_password: String,
    salt: String,
    name: String,
    groups: [{
        _id: { type: Schema.Types.ObjectId, required: true, ref: 'groups' }, 
        name: String
    }]
});

var groupSchema= mongoose.Schema({ 
    name: String,
    creator: Schema.Types.ObjectId,
    users: [{
        _id: { type: Schema.Types.ObjectId, required: true, ref: 'users' }, 
        rankInGroup: { type: Number, required: true }
    }]
});

此时我有一个函数,它接受以下参数:创建组的用户的电子邮件地址 (groupCreator),新组的名称 (newGroupName),以及需要添加到组中的用户 (newGroupMembers) 的用户 ID。该函数首先找到需要添加到组的用户(使用this method),然后将这些用户的用户ID添加到组文档中的用户数组中,如下所示:

function(groupCreator, newGroupName, newGroupMembers , callback) {
    userModel.findOne({
        email: emailGroupCreator
    }, function(err,creator){
        //load document of user who creates the group into creator variable
        var newGroup = new groupModel({ 
            name: newGroupName, 
            creator: creator._id, 
            users: [{_id: creator._id, rank: 0}] //add group creator to the group
            });

        userModel.find({
            email: { $in: newGroupMembers }
        }, function(err,users){                         
            //for now assume no error occurred fetching users
            users.forEach(function(user) {                              
                newGroup.users.push({_id: user._id, rank: 0}); //add user to group
                user.groups.push({_id:newGroup._id,name:newGroup.name}); //add group to user
            }
            newGroup.save(function (err) {
            //for now assume no error occurred
            creator.groups.push({_id: newGroup._id, name: newGroup.name}); //add group to creator
            creator.save(function (err) {
                //for now assume no error occurred

                /* save/update the user documents here by doing something like
                newMembers.forEach(function(newMember) {
                    newMember.save(function (err) {
                        if(err){
                            callback(500, {success: false, response: "Group created but failure while adding group to user: "+newMember.email});
                        }
                    });
                });
                callback(200, {success: true, response: "Group created successfully!"});
                */ 
            });
        }
    });
}

所以我希望这个函数:

  • 根据groupCreator中存储的邮箱地址查找组创建者的用户文档
  • 创建一个新组 (newGroup) 并将创建者添加到其用户数组中
  • 找到所有需要添加到组的用户
  • 使用新创建组的 groupid (newGroup._id) 更新所有用户文档中的组数组
  • 如果所有这些都成功执行,则进行回调

这里的问题是添加到组的用户的所有用户文档的更新都是异步发生的,但我想确保在返回成功或失败回调之前所有用户文档都正确更新。在继续使用其余代码(可能不使用 foreach)之前,如何更新所有用户文档?我最初检索所有用户文档的方法是好的还是有更好的方法来做到这一点?

所以底线问题是;执行完所有保存操作后,如何保存多个用户文档并继续执行其余代码(发送回调以通知成功或失败),或者有没有办法一次保存所有文档?

NB 我想要在用户和组文档中(一些)相同的信息的原因是因为我不想在用户登录时为他加载所有组信息,只加载基本组信息.另请参阅多对多关系部分下的this source

【问题讨论】:

  • 这里的基本情况是 JavaScript .forEach() 不能尊重异步回调。但是在您的问题中基本上不清楚您的数据(未在列出的代码中定义的引用的变量)来自何处或更新的全部意图。通过在问题中包含其他相关操作并解释源数据样本的预期结果,您可以更清楚地说明这些要点。
  • 我添加了更多信息和该函数应该做什么的列表:)
  • 你可以使用像async.each这样的异步迭代器来做这种事情。
  • 嗯,看起来很有趣,我只是偶然发现了这个页面 (sebastianseilund.com/nodejs-async-in-practice),它指的是 async.parallel。会调查的!

标签: node.js mongodb mongoose


【解决方案1】:

JohnnyHK 为我指明了正确的方向; async.each 可以迭代文档并一次更新它们。之后,其余代码将被执行。这就是我的代码现在的样子:

async.each(groupMembersDocs, function (newMember, loopCallback) {
    //console.log('Processing user ' + newMember.email + '\n');
    userModel.update({
        email: newMember.email
    }, {
        $push: { 'groups' : {_id: newGroup._id, name: newGroup.name} }
    }, function (err, data) { 
        if(err){
            console.log("error: "+err);
            loopCallback('Failure.. :'+err);
        } else{
            newGroup.users.push({_id: newMember._id, rank: -1});
            loopCallback();
        }
    });
}, function (err){
    if(err){
        console.log("error: "+err);
        callback(500, {success: false, response: "Error while adding users to group"});
    } else{
        newGroup.save(function (err) {
            callback(201, {success: true, response: "Group created successfully"});
        });
    }
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-05
    • 2019-02-11
    • 2015-10-13
    • 2021-03-21
    • 2018-04-18
    • 2012-10-27
    相关资源
    最近更新 更多