2015-10-15 123 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"}); 
     }); 
    } 
})