2013-02-06 151 views
8

我最近開始使用MongoDB,並且有關於更新文檔中數組的問題。 我得到的結構是這樣的:MongoDB更新數組的多個記錄

{ 
"_id" : ObjectId(), 
"post" : "", 
"comments" : [ 
     { 
       "user" : "test", 
       "avatar" : "/static/avatars/asd.jpg", 
       "text" : "....." 
     } 
     { 
       "user" : "test", 
       "avatar" : "/static/avatars/asd.jpg", 
       "text" : "....." 
     } 
     { 
       "user" : "test", 
       "avatar" : "/static/avatars/asd.jpg", 
       "text" : "....." 
     } 
     ... 
    ] 
} 

我試圖執行以下查詢:

update({"comments.user":"test"},{$set:{"comments.$.avatar": "new_avatar.jpg"}},false,true) 

的問題是其更新的所有文件,但它僅更新在每一個第一個數組元素文件。有沒有辦法更新所有數組元素,或者我應該嘗試手動執行它? 謝謝。

回答

19

您無法在單個更新操作中修改多個數組元素。因此,您必須重複更新才能遷移需要修改多個數組元素的文檔。您可以通過每個文檔集合中迭代,反覆應用的更新與$elemMatch直到文檔做這一切的它的相關的備註,例如:

 
db.collection.find().forEach(function(doc) { 
    do { 
    db.collection.update({_id: doc._id, 
          comments:{$elemMatch:{user:"test", 
               avatar:{$ne:"new_avatar.jpg"}}}}, 
         {$set:{"comments.$.avatar":"new_avatar.jpg"}}); 
    } while (db.getPrevError().n != 0); 
}) 

注意,如果這個操作的效率是一個要求你的應用程序,你應該規範你的模式,以便用戶頭像的位置存儲在單個文檔中,而不是在每個評論中。

+0

感謝您的回答。那麼因爲mongo沒有加入,我想用博客系統評論,我想在他的評論旁邊顯示每個用戶頭像。任何建議我應該如何構建我的模式? –

+0

從概念上講,你需要在某處存儲一個user => avatar map。您可以將每個用戶的頭像存儲在用戶文檔中(在您的用戶集合中),或者,您可以爲給定博客條目的評論者在該博客條目的文檔字段中存儲用戶=>頭像地圖。請參閱http://docs.mongodb.org/manual/applications/database-references/,瞭解MongoDB中規範化的輕量化處理,以及http://docs.mongodb.org/manual/use-cases/storing-comments/ for一個「用戶評論」用例分析。 –

+0

是的,我在看到你的答案之前就想出瞭解決方案。無論如何非常感謝你@Jason。 –

5

一個解決方案可能是創建一個函數用於forEach並對其進行評估(因此它可以快速運行)。假設您的集合是「文章」,則可以運行以下操作:

var runUpdate = function(){ 
    db.article.find({"comments.user":"test").forEach(function(article) { 
     for(var i in article.comments){ 
      article.comments[i].avatar = 'new_avatar.jpg'; 
     } 
     db.article.save(article); 
    }); 
}; 

db.eval(runUpdate); 
-1

好像你可以這樣做:

db.yourCollection.update({"comments.user":"test"},{$set:{"comments.0.avatar": "new_avatar.jpg", "comments.1.avatar": "new_avatar.jpg", etc...}) 

所以,如果你有數組元素的少量已知數量,這可能是更容易一些的事情。如果你想要像「評論。*。頭像」的東西 - 不知道如何做到這一點。它可能不是那麼好,你有這麼多的數據複製壽..

1

如果你知道索引要更新,你可以像這樣沒有問題做到這一點:

var update = { $set: {} }; 
for (var i = 0; i < indexesToUpdate.length; ++i) { 
    update.$set[`comments.${indexesToUpdate[i]}. avatar`] = "new_avatar.jpg"; 
} 
Comments.update({ "comments.user":"test" }, update, function(error) { 
    // ... 
}); 
  • 注意IDE的必須不會接受語法,但您可以忽略它。