0

多个文档,我有一些40000条记录,我需要更新planId字段和记录复制到同一个集合。 现在我使用的基本MongoDB的复制和更新在同一个集合

linkModel.find({},callback) & linkModel.insertMany([linksArray],callback) 

但它占用了大量的时间。 我已经试过了,但聚集,而我想更新它不能代替$out运营商替换现有的集合。

到目前为止,我已经尝试了三个步骤:

db.links.aggregate([ { $match: { planId: ObjectId("5732f50a6886e5421259e823") } }, { $out: "temp" } ]);

db.temp.updateMany({planId:ObjectId("5732f50a6886e5421259e823")},{$set:{planId:ObjectId("5791b25f203b5e92316e60c3")}})

db.temp.copyTo("links")

但即使CopyTo方法将是缓慢的。 对此有更快的方法吗?使用Bulk API散装做更新的

回答

0

利用。他们提供更好的性能,你会说1000,你不是每次发送请求给服务器,这是更为有效的批次中每1000个请求被发送操作的服务器,但只有一次。

下面演示了这种方法,第一个例子使用MongoDB中的版本>= 2.6 and < 3.2提供的大宗原料药。它由所有Cost领域不断变化的浮动值字段更新集合中的所有 文件:

var bulk = db.links.initializeUnorderedBulkOp(), 
    counter = 0; 

db.links.find({ planId: ObjectId("5732f50a6886e5421259e823") }) 
     .snapshot().forEach(function (doc) {   
    bulk.find({ "_id": doc._id }).updateOne({ 
     "$set": { "planId": ObjectId("5791b25f203b5e92316e60c3") } 
    }); 

    counter++; 
    if (counter % 1000 == 0) { 
     bulk.execute(); // Execute per 1000 operations 
     // re-initialize every 1000 update statements 
     bulk = db.links.initializeUnorderedBulkOp(); 
    } 
}) 
// Clean up remaining operations in queue 
if (counter % 1000 != 0) { bulk.execute(); } 

下一个例子适用于新的MongoDB 3.2版具有自deprecatedBulk API和提供较新的一套使用bulkWrite()的API。

它使用与上述相同的游标,但使用相同的forEach()游标方法创建带批量操作的阵列,以将每个批量写入文档推送到数组。因为写命令可以接受不超过1000点的操作,你需要将你的操作有最多1000的操作和重新intialise数组时,循环打1000迭代:

var cursor = db.links.find({ planId: ObjectId("5732f50a6886e5421259e823") }).snapshot(), 
    bulkUpdateOps = []; 

cursor.forEach(function(doc){   
    bulkUpdateOps.push({ 
     "updateOne": { 
      "filter": { "_id": doc._id }, 
      "update": { "$set": { "planId": ObjectId("5791b25f203b5e92316e60c3") } } 
     } 
    }); 

    if (bulkUpdateOps.length == 1000) { 
     db.links.bulkWrite(bulkUpdateOps); 
     bulkUpdateOps = []; 
    } 
});   

if (bulkUpdateOps.length > 0) { db.links.bulkWrite(bulkUpdateOps); }