2015-10-15 106 views
0

同步更新文档我不知道什么是最好的办法是实现Node.js的下列情况和猫鼬:创建和使用猫鼬

我在与用户的集合,并与团体的集合。我希望用户能够创建新的群组并向其添加人员(与创建新的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)。这个函数首先发现需要被添加到组(使用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其电子邮件地址
  • 创建新组(新闻组)和创建者添加到其用户阵列
  • 找到所有的网友认为需要添加到组
  • 更新组阵列,使新创建的组
  • 的GROUPID(newGroup._id)中的所有用户的文件做一个回调,如果这一切都是成功执行

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

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

NB我之所以要在用户和组文件中使用相同的信息,是因为如果用户登录,我不想加载用户的所有组信息,只有基本组信息。参见this source下的多对多关系部分。

+2

这里的基础是JavaScript'.forEach()'不能使用异步回调。但是在你的问题中,你的数据(所引用的变量在列出的代码中没有定义)来自你的更新的完整意图还是基本不清楚。通过在问题中包含其他相关操作并解释源数据样本的预期结果,可以使这些要点更清晰。 –

+0

我已经添加了一些更多的信息和这个函数应该做什么的列表:) – Koningh

+1

你可以使用异步迭代器,比如['async.each'](https://github.com/caolan/async#each)做这种事情。 – JohnnyHK

回答

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"}); 
     }); 
    } 
})