简体   繁体   English

MongoDB复制和更新同一集合中的多个文档

[英]MongoDB Copy and Update Multiple Documents in same collection

I have some 40000 records For which I need to update a planId field and copy the records to same collection. 我有一些40000条记录,我需要为其更新planId字段并将记录复制到同一集合中。 Right Now I am using the basic 现在我正在使用基本

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

But it takes up a lot of time. 但这会占用很多时间。 I have tried the aggregation but $out operator replaces the existing collection whereas I want to update it not replace. 我尝试了聚合,但是$out运算符替换了现有集合,而我想更新它而不替换它。

The three steps I have tried so far: 到目前为止,我尝试了三个步骤:

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

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

db.temp.copyTo("links") , db.temp.copyTo("links")

But even copyTo method is slow. 但是,即使copyTo方法也很慢。 Is there a faster approach for this? 有没有更快的方法呢?

Take advantage of using the Bulk API for doing the updates in bulk. 利用Bulk API进行Bulk API更新。 They offer better performance as you will be sending the operations to the server in batches of say 1000, which is much more efficient as you are not sending every request to the server, but just once in every 1000 requests. 它们可以提供更好的性能,因为您可以将操作批量发送到服务器(例如1000),这效率更高,因为您不是将每个请求发送到服务器,而是每1000个请求发送一次。

The following demonstrates this approach, the first example uses the Bulk API available in MongoDB versions >= 2.6 and < 3.2 . 下面演示了这种方法,第一个示例使用MongoDB版本>= 2.6 and < 3.2可用的Bulk API。 It updates all the documents in the collection by changing all the Cost fields to floating value fields: 通过将所有“ 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(); }

The next example applies to the new MongoDB version 3.2 which has since deprecated the Bulk API and provided a newer set of apis using bulkWrite() . 下一个示例适用于新的MongoDB 3.2版,此版本已弃用 Bulk API并使用bulkWrite()提供了一组较新的api。

It uses the same cursors as above but creates the arrays with the bulk operations using the same forEach() cursor method to push each bulk write document to the array. 它使用与上面相同的游标,但是使用相同的forEach()游标方法通过批量操作创建数组,以将每个批量写入文档推入数组。 Because write commands can accept no more than 1000 operations, you will need to group your operations to have at most 1000 operations and re-intialise the array when loop hit the 1000 iteration: 由于写命令最多只能接受1000个操作,因此您需要将操作分组以最多具有1000个操作,并在循环达到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); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM