2016-09-21 14 views
1

mongodbコレクションの一括更新を行う必要があります。_tというフィールドを更新する110Mドキュメントがあります。エポックからの秒数は{$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(); 

しかし、最初の1で、私はforEach()にコールバック関数を持っているのに対し、私は、ドキュメントを参照するかどうかはわかりません。

助けてくれてありがとう、Jared。

+0

スクリプトを実行したときにコンソールからログが取得されましたか?どのMongoDBのバージョンを使用していますか? – chridam

+0

私は '3.2.7'を使用していますが、出力もログも出力しませんでしたが、明示的に何も記録しませんでした。 – Jared

+0

すべての110M操作をまとめて格納するために 'bulkOps'をビルドすることはおそらく問題です。 1000要素になるたびに 'bulkWrite(bulkOps)'を呼び出して、それをクリアして1000を構築してください。 – JohnnyHK

答えて

1

find()は、非同期に解決されるカーソルを返します。 forEachループの実行が完了するまでには、既に空のbulkOps配列でdb.siteEvents.bulkWrite(bulkOps);が呼び出されています。

mongodbエンジン内でjavascriptを実行すると約束がサポートされているかどうかわからないので、最も簡単なことは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);  
}); 
関連する問題