2016-09-21 253 views
1

我需要使用110M文檔對mongodb集合進行批量更新,這些文檔更新字段_t,這是從紀元開始的秒數{$type : 1}。我需要將數據庫中的每個_t轉換爲ISODate()大批量更新MongoDB - forEach()文檔

我嘗試了劇本updateDate.js這樣的:

var bulkOps = []; 

db.siteEvents.find({"_t": {"$exists": true, "$type": 1 }}).forEach(function (doc) { 
    var epoch = doc._t; 
    newDate = new ISODate(epoch * 1000); 

    bulkOps.push(   
     { 
      "updateOne": { 
       "filter": { "_id": doc._id } ,    
       "update": { "$set": { "_t": newDate } } 
      }   
     }   
    );  
}); 

db.siteEvents.bulkWrite(bulkOps); 

但我跑這個腳本mongo <connection details...> updateDate.js,跑了一會,但沒有作出任何更新。

使用該文檔頁面作爲參考,我得到了這一點:

var bulk = db.siteEvents.initializeUnorderedBulkOp(); 

bulk.find({ "_t": { $type : 1 } }).update({ $set: { <UNSURE HOW TO REFERENCE DOC HERE> } }); 

bulk.execute(); 

但我不知道如何引用文件,而在最初的一個我對forEach()一個回調函數。傑瑞德謝謝你的幫助。

+0

當您運行腳本時,您是否從控制檯得到任何日誌?你使用哪個MongoDB版本? – chridam

+0

我正在使用'3.2.7',它沒有提供任何輸出或記錄,但我沒有明確記錄任何內容。 – Jared

+0

建立'bulkOps'以一次包含所有110M操作可能是您的問題。嘗試每次獲取1000個元素時調用'bulkWrite(bulkOps)',然後清除它並構建下一個1000等。 – JohnnyHK

回答

1

find()返回一個異步解析的遊標。在您的forEach循環完成運行時,db.siteEvents.bulkWrite(bulkOps);已被調用,並且有一個空的bulkOps數組。

我不知道在mongodb引擎中運行javascript是否支持promise,所以最簡單的方法是調用find().toArray(),然後在回調中移動循環和bulkWrite。沿着這些線:

var bulkOps = []; 

db.siteEvents.find({"_t": {"$exists": true, "$type": 1 }}).toArray(function(err, docs) { 
    docs.forEach(function (doc) { 
     var epoch = doc._t; 
     newDate = new ISODate(epoch * 1000); 

     bulkOps.push(   
     { 
      "updateOne": { 
       "filter": { "_id": doc._id } ,    
       "update": { "$set": { "_t": newDate } } 
      }   
     }   
    ); 
    }); 
    db.siteEvents.bulkWrite(bulkOps);  
});