我需要使用110M文档对mongodb
集合进行批量更新,这些文档会更新字段_t
,这是自纪元以来的{$type : 1}
秒数。我需要将数据库中的每个_t
转换为ISODate()
。
我尝试了这样的脚本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()
上有一个回调函数。
感谢你的帮助,Jared。
答案 0 :(得分:2)
find()
返回异步解析的游标。当你的forEach循环运行完毕时,db.siteEvents.bulkWrite(bulkOps);
已经被调用了一个空的bulkOps数组。
我不知道在mongodb引擎中运行javascript是否支持promises,所以最简单的方法是调用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);
});