2015-10-17 87 views
-1

我有一個像MongoDB的文檔:更新陣列中的所有元素在MongoDB中

{ 
    "name" : "JohnDoe", 
    "adds" : [ 
     { 
      "status" : "PENDING", 
      "date" : "2015-09-23" 
     }, 
     { 
      "status" : "PENDING", 
      "date" : "2015-10-01" 
     } 
    ] 
} 

我想更新所有的數組元素,如:

collection.update({'name':'JohnDoe'}, {'$set':{'adds.status':'APPROVED'}}). 

如何做到這一點?

編輯:大多數解決方案表示使用位置運算符來選擇數組元素,然後使用運算符來更新該元素。但在我的情況下,我不得不更新數組中的每個元素。

+0

@sheilak我發佈的用戶可以選擇一個單獨的數組元素,然後他可以使用位置運算符更新它。但我必須更新數組中的每個元素。 –

+0

該問題的答案解釋說您無法在一次更新中對數組中的所有項執行$ set。接受的答案與有關該問題的開放JIRA票證相關聯。還有多個變通辦法。 – sheilak

回答

1

如前所述,主要問題在這裏是與記錄在這個長期存在的問題的位置操作多個元素的更新:http://jira.mongodb.org/browse/SERVER-1243

的基本情況,因此沒有單一的執行可以做到這一點,所以在爲了處理多個數組元素,您需要一些方法來確定需要更新多少個元素,併爲每個元素處理一個更新語句。

一種簡化的方法來這通常使用Bulk Operations處理什麼最終被「多張」更新操作作爲一個單一的請求和響應到服務器:

var bulk = db.collection.initializeOrderedBulkOp(), 
    count = 0; 

db.collection.find({ "name": "John Doe", "adds.status": "PENDING" }).forEach(function(doc) { 
    doc.adds.filter(function(add){ return add.status = "PENDING" }).forEach(function(add) { 
     bulk.find({ "_id": doc._id, "adds.status": "PENDING" }).updateOne({ 
      "$set": { "adds.$.status": "APPROVED" } 
     }); 
     count++; 

     // Execute once in 1000 statements created and re-init 
     if (count % 1000 == 0) { 
      bulk.execute(); 
      bulk = db.collection.initializeOrderedBulkOp(); 
     } 
    }); 
}); 

// Execute any pending operations 
if (count % 1000 != 0) 
    bulk.execute(); 

如果你的文件的更新是相當小的,或實際上只有一個文檔,那麼您可以放棄count檢查,並簡單地在所需循環中追加所有批量更新,並在所有循環結束時只執行一次。

較長的解釋和候補可以How to Update Multiple Array Elements中找到,但所有回落到不同的方法來更新元件匹配和處理positional $更新複式次,或者匹配,或者直到沒有更多的修改的文檔返回的每個文檔。