2016-09-21 3 views
1

Мне нужно сделать массовое обновление коллекции mongodb с документами 110M, которые обновляют поле _t, которое является числом {$type : 1} секунд с эпохи. Мне нужно конвертировать каждые _t в базу данных до ISODate().Large Bulk Update MongoDB - forEach() document

Я попробовал сценарий 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 сразу, вероятно, ваша проблема. Попробуйте вызвать 'bulkWrite (bulkOps)' каждый раз, когда он получит 1000 элементов, а затем очистит его и построит следующие 1000 и т. Д. – JohnnyHK

ответ

1

find() возвращает курсор, который разрешен асинхронно. К моменту завершения цикла forEach db.siteEvents.bulkWrite(bulkOps); уже вызывается с пустым массивом arrayOpps.

Не знаю, поддерживает ли javascript внутри движка mongodb обещания, поэтому проще всего позвонить в 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);  
});