MongoDB:将一个数组复制到同一文档中的另一个数组 [英] MongoDB: Copying an array to another array in the same document

查看:95
本文介绍了MongoDB:将一个数组复制到同一文档中的另一个数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在与MongoDB一起在在线珠宝商店工作,我需要将品牌"阵列中包含的品牌复制到一个名为"brandsNetherlands"的新阵列中.

  {"_id":ObjectId("569d03b66abefa8be9c49f26"),品牌":[品牌1"品牌2"品牌3"],名称":家庭珠宝",地址" : "","housenr":",邮政编码":"1234 AQ","city":阿姆斯特丹",电话":"+31 570-514200","email":"jewelry@email.nl","web":"http://www.familyjewels.nl/","kind":钟表","country":"Nederland","brandsNetherlands":[]} 

这是批发商"集合中所含文件之一的当前集合的一个示例.我需要一个非静态脚本,该脚本允许我将品牌"数组中列出的品牌移动或复制到空的"brandsNetherlands"数组中.这可能吗?

解决方案

对于较小的数据,您可以通过使用


虽然这对于小型集合是最佳选择,但是由于循环大型数据集并将每个请求的每个更新操作发送到服务器会导致计算量的损失,因此大大降低了大型集合的性能.

Bulk() API可以挽救资源,并大大提高了性能,因为写入操作仅批量发送到服务器一次.由于该方法不会将每个写入请求都发送到服务器,因此可以实现效率(与 forEach() 循环创建批次,我们可以按如下方式批量更新集合.

在本演示中, Bulk() 在MongoDB版本> = 2.6和<3.2 使用 initializeUnorderedBulkOp() 方法可并行执行,并以不确定的顺序执行批处理中的写操作:

var bulk = db.wholesalers.initializeUnorderedBulkOp(),计数器= 0;//计数器以跟踪批次更新大小

  db.wholesalers.find({"brands":{"$ exists":true,"$ type":4}}).snapshot().forEach(function(doc){bulk.find({"_id":doc._id}).updateOne({"$ set":{"brandsNetherlands":doc.brands}});计数器++;//增量计数器如果(计数器%1000 == 0){bulk.execute();//每1000个操作执行一次,每1000条更新语句重新初始化一次批量= db.wholesalers.initializeUnorderedBulkOp();}}); 


下一个示例适用于新的MongoDB版本 3.2 ,此版本已弃用 forEach() 游标方法,用于将每个批量写入文档推入数组.由于写命令最多只能接受1000个操作,因此需要对操作进行分组以使最多具有1000个操作,并在循环达到1000次迭代时重新初始化数组:

  var cursor = db.wholesalers.find({"brands":{"$ exists":true,"$ type":4}}),bulkUpdateOps = [];cursor.snapshot().forEach(function(doc){bulkUpdateOps.push({"updateOne":{"filter":{"_id":doc._id},"update":{"$ set":{"brandsNetherlands":doc.brands}}}});如果(bulkUpdateOps.length === 1000){db.wholesalers.bulkWrite(bulkUpdateOps);bulkUpdateOps = [];}});如果(bulkUpdateOps.length> 0){db.wholesalers.bulkWrite(bulkUpdateOps);} 

I'm currently working on an online jewelry store with MongoDB, and I need to copy the brands contained in the "brands" array into a new array called "brandsNetherlands".

{    
            "_id" : ObjectId("569d03b66abefa8be9c49f26"),
            "brands" : [
                    "Brand1"
                    "Brand2"
                    "Brand3"
            ],
            "name" : "Family Jewels",
            "address" : "",
            "housenr" : "",
            "postalcode" : "1234 AQ",
            "city" : "Amsterdam",
            "phone" : "+31 570 - 514200",
            "email" : "jewelry@email.nl",
            "web" : "http://www.familyjewels.nl/",
            "kind" : "horloges",
            "country" : "Nederland",
            "brandsNetherlands" : [ ]
}

This is an example of the current build-up of one of the documents contained in tbe "wholesalers" collection. I need a non-static script that will allow me to move or copy the brands listed in the "brands" array into the empty "brandsNetherlands" array. Is this possible?

解决方案

For relatively small data, you can achieve the above by iterating the collection using a snapshot with the cursor's forEach() method and updating each document as follows:

db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 
    db.wholesalers.updateOne(
        { "_id": doc._id },
        { "$set": { "brandsNetherlands": doc.brands } }
    );
});


Whilst this is optimal for small collections, performance with large collections is greatly reduced since looping through a large dataset and sending each update operation per request to the server incurs a computational penalty.

The Bulk() API comes to the rescue and greatly improves performance since write operations are sent to the server only once in bulk. Efficiency is achieved since the method does not send every write request to the server (as with the current update statement within the forEach() loop) but just once in every 1000 requests, thus making updates more efficient and quicker than currently is.

Using the same concept above with the forEach() loop to create the batches, we can update the collection in bulk as follows.

In this demonstration the Bulk() API available in MongoDB versions >= 2.6 and < 3.2 uses the initializeUnorderedBulkOp() method to execute in parallel, as well as in a nondeterministic order, the write operations in the batches:

var bulk = db.wholesalers.initializeUnorderedBulkOp(), counter = 0; // counter to keep track of the batch update size

db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 

    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "brandsNetherlands": doc.brands } 
    });

    counter++; // increment counter
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.wholesalers.initializeUnorderedBulkOp();
    }
});


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().

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. Because write commands can accept no more than 1000 operations, there's need to group operations to have at most 1000 operations and re-intialise the array when the loop hits the 1000 iteration:

var cursor = db.wholesalers.find({
         "brands": { "$exists": true, "$type": 4 } 
    }),
    bulkUpdateOps = [];

cursor.snapshot().forEach(function(doc){ 
    bulkUpdateOps.push({ 
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": { "$set": { "brandsNetherlands": doc.brands } }
         }
    });

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

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

这篇关于MongoDB:将一个数组复制到同一文档中的另一个数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆