2016-08-24 16 views
1

我在mongodb的以下結構:MongoDB的 - 與動態字段轉換地圖以陣列

db.coll1.findOne({}, {myMap:1}): 

{ 
    "x1-y1": { 
    x: x1, 
    y: y1, 
    etc: .. 
    }, 
    "x2-y2": {..} 
} 

其中x和y是在範圍0..100。

我認爲這不是一個好主意,用動態命名字段,我想這個地圖轉換成數組:

db.coll1.findOne({}, {myArr:1}): 

{[ 
    { 
    x: x1, 
    y: y1, 
    etc: .. 
    }, 
    { .. } 
]} 

我需要這些字段沒有索引。如何才能做到這一點?

回答

1

一般的想法是循環訪問集合,爲每個文檔映射將子文檔鍵映射到新數組,並使用現在存儲數組的字段更新文檔。直覺最好用一個例子來解釋,這假設你有收集幾個文件:

填充測試集:

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(); 
+0

謝謝你的回答,但我有一些麻煩。在執行「更新」代碼後,我得到:「myMap」:[null,null]。此外,我沒有bulkUpdate(),也許這是因爲mongo版本是2.6.11 – awfun

+0

我已更新我的答案,以使用適用於您的MongoDB版本的批量API。你能編輯你的問題來添加實際的文檔模式,或許這些密鑰與上面代碼中的密鑰不一樣嗎? – chridam

+1

問題出在Object.keys ... return doc [key] - 應該返回doc.myMap [key]。你能否在你的回答中修正這個錯字?非常感謝您的答案! – awfun