一般的想法是循環訪問集合,爲每個文檔映射將子文檔鍵映射到新數組,並使用現在存儲數組的字段更新文檔。直覺最好用一個例子來解釋,這假設你有收集幾個文件:
填充測試集:
db.test.insert({
"myMap": {
"0-1": {
"x": 0,
"y": 1
},
"1-2": {
"x": 1,
"y": 2
}
}
})
更新
db.test.find({}).forEach(function(doc){
var new_arr = Object.keys(doc.myMap).map(function(key){return doc.myMap[key]});
doc["myMap"] = new_arr;
db.test.save(doc);
})
查詢
如果您MongDB版本確實
var ops = [];
db.test.find({}).forEach(function(doc){
var new_arr = Object.keys(doc.myMap).map(function(key){return doc.myMap[key]});
ops.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "myMap": new_arr } }
}
});
if (ops.length == 1000) {
db.test.bulkWrite(ops);
ops = [];
}
});
if (ops.length > 0) { db.test.bulkWrite(ops); }
:3210
樣本輸出
{
"_id" : ObjectId("57bdae6ce3f9ad02c421e448"),
"myMap" : [
{
"x" : 0,
"y" : 1
},
{
"x" : 1,
"y" : 2
}
]
}
對於一個更大的集合,最好地利用與bulkWrite()
API更新不支持bulkWrite API,使用2.6和3.0版本中提供的Bulk()
方法:
var bulk = db.test.initializeUnorderedBulkOp(),
counter = 0;
db.test.find({}).forEach(function(doc) {
var new_arr = Object.keys(doc.myMap).map(function(key){return doc.myMap[key]});
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "myMap": new_arr }
});
counter++;
if (counter % 1000 === 0) {
bulk.execute();
bulk = db.test.initializeUnorderedBulkOp();
}
});
if (counter % 1000 !== 0)
bulk.execute();
謝謝你的回答,但我有一些麻煩。在執行「更新」代碼後,我得到:「myMap」:[null,null]。此外,我沒有bulkUpdate(),也許這是因爲mongo版本是2.6.11 – awfun
我已更新我的答案,以使用適用於您的MongoDB版本的批量API。你能編輯你的問題來添加實際的文檔模式,或許這些密鑰與上面代碼中的密鑰不一樣嗎? – chridam
問題出在Object.keys ... return doc [key] - 應該返回doc.myMap [key]。你能否在你的回答中修正這個錯字?非常感謝您的答案! – awfun