以您目前的模式,你會需要一種機制來獲取在執行更新之前需要組裝查詢的動態密鑰列表,並且可以採用以下方法之一:MapReduce。就拿下面的地圖,減少操作,將填充單獨收集的所有鍵作爲_id
值:
mr = db.runCommand({
"mapreduce": "test",
"map" : function() {
for (var key in this.image) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "test_keys"
})
要獲得所有動態密鑰列表,在結果集合運行不同:
> db[mr.result].distinct("_id")
[ "unknown-node-1", "unknown-node-2" ]
現在給出上面的列表,您可以通過創建一個將其屬性設置爲循環的對象來組裝您的查詢。一般來說,如果你知道這個組鍵,您的查詢都會有這樣的結構:
var query = {
"image.unknown-node-1.id": 123
},
update = {
"$unset": {
"image.unknown-node-1": ""
}
};
db.test.update(query, update);
但由於節點是動態的,你將不得不遍歷從精簡操作並且爲每個元素返回的列表,創建查詢和更新參數如上更新集合。這個列表可能很大,所以爲了獲得最大效率,如果你的MongoDB服務器是2.6或更新版本,最好利用使用寫命令Bulk API,以允許執行批量更新操作,這些操作只是抽象服務器可以輕鬆構建批量操作,從而可以在大型集合中獲得性能提升。這些批量操作來主要有兩種形式:
- 有序批量操作。這些操作按順序執行所有操作,並在第一次寫入錯誤時出錯。
- 無序批量操作。這些操作並行執行所有操作並聚合所有錯誤。無序批量操作不保證執行順序。
請注意,對於比2.6更早的服務器,API將下載轉換操作。然而,它不可能下變換100%,因此可能會出現一些無法正確報告正確數字的邊緣情況。
在你的情況,你可以實現這樣的大宗原料藥更新操作:
mr = db.runCommand({
"mapreduce": "test",
"map" : function() {
for (var key in this.image) { emit(key, null); }
},
"reduce" : function(key, stuff) { return null; },
"out": "test_keys"
})
// Get the dynamic keys
var dynamic_keys = db[mr.result].distinct("_id");
// Get the collection and bulk api artefacts
var bulk = db.test.initializeUnorderedBulkOp(), // Initialize the Unordered Batch
counter = 0;
// Execute the each command, triggers for each key
dynamic_keys.forEach(function(key) {
// Create the query and update documents
var query = {},
update = {
"$unset": {}
};
query["image."+ key +".id"] = 123;
update["$unset"]["image." + key] = ";"
bulk.find(query).update(update);
counter++;
if (counter % 100 == 0) {
bulk.execute() {
// re-initialise batch operation
bulk = db.test.initializeUnorderedBulkOp();
}
});
if (counter % 100 != 0) { bulk.execute(); }
如果你不事先知道該子文檔的名稱,你不能和你有正確的文檔結構做現在。如果將所有「unknown-node-N」文檔放入數組中,則可以執行此操作。 –