我有一个包含1000000多个文档的mongoDB集合,我想用专用信息逐个更新每个文档(每个文档都有来自其他集合的信息)。
目前我正在使用一个游标来获取集合中的所有数据,并通过Node.js的异步模块更新每个记录
获取所有文档:
inst.db.collection(association.collection, function(err, collection) {
collection.find({}, {}, function(err, cursor) {
cursor.toArray(function(err, items){
......
);
});
});
更新每个文档:
items.forEach(function(item) {
// *** do some stuff with item, add field etc.
tasks.push(function(nextTask) {
inst.db.collection(association.collection, function(err, collection) {
if (err) callback(err, null);
collection.save(item, nextTask);
});
});
});
并行调用“保存”任务
async.parallel(tasks, function(err, results) {
callback(err, results);
});
你会以更有效的方式进行这种类型的操作吗?我的意思是如何避免加载游标的初始“查找”。现在是否可以通过doc了解所有文档应该更新的操作文档?
感谢您的支持。
答案 0 :(得分:1)
你的问题激励我为你的问题创建Gist to do some performance testing不同的方法。
以下是在localhost上使用MongoDB的小型EC2实例上运行的结果。测试场景是对100000个元素集合的每个文档进行唯一操作。
虽然没有包含,但我也用MapReduce做了一个测试,用作服务器端过滤器,运行时间约为19秒。我本来希望类似地使用“聚合”作为服务器端过滤器,但它还没有输出到集合的选项。
最重要的答案是,如果你可以逃脱它,最快的选择是通过游标从初始集合中提取项目,在本地更新它们并将它们插入到大块的新集合中。然后你可以用旧的交换新的集合。
如果需要保持数据库处于活动状态,那么最好的选择是使用带有大型batchSize的游标,并更新文档。 “保存”调用比“更新”慢,因为它需要替换整个文档,并且可能还需要重新索引它。