与mongoose同步创建和更新文档

时间:2015-10-15 12:51:46

标签: node.js mongodb mongoose

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

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

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 ),新组的名称( newGroupName < / em>),以及需要添加到组中的用户的用户ID( newGroupMembers )。此函数首先找到需要添加到组中的用户(使用this method),然后将这些用户的用户ID添加到组文档中的users数组中,如下所示:

{{1}}

所以我希望这个功能:

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

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

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

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

1 个答案:

答案 0 :(得分: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"});
        });
    }
})