更新mongoDB中的联接。可能吗?

时间:2016-06-30 07:28:50

标签: mongodb

鉴于这三个文件:

db.test.save({"_id":1, "foo":"bar1", "xKey": "xVal1"});
db.test.save({"_id":2, "foo":"bar2", "xKey": "xVal2"});
db.test.save({"_id":3, "foo":"bar3", "xKey": "xVal3"});

引用这些文档的单独信息数组:

[{"_id":1, "foo":"bar1Upd"},{"_id":2, "foo":"bar2Upd"}]

是否可以在一次操作中更新两个引用文档(1和2)上的“foo”?

我知道我可以遍历数组并逐个执行,但是我有数千个文档,这意味着往返服务器的次数过多。

非常感谢你的想法。

1 个答案:

答案 0 :(得分:3)

无法更新" foo"在单个原子操作中的两个引用文档(1和2)上,因为MongoDB没有这样的机制。但是,看到您有一个大型集合,一个选项是利用 Bulk API ,它允许您批量发送更新而不是每次更新请求到服务器。

该过程涉及循环数组中所有匹配的文档并处理批量更新,这将至少允许在单个请求中使用单一响应发送许多操作。

这为您提供了更好的性能,因为您不会将每个请求发送到服务器,而是每500个请求中只发送一次,从而使您的更新更加高效和快捷。

- 的 修改 -

选择较低值的原因通常是受控制的选择。正如那里的文档所述,默认情况下MongoDB将发送到server in batches of 1000 operations at a time at maximum,并且无法保证确保这些默认的1000个操作请求实际适合16MB BSON limit。所以你仍然需要在" safe"并且施加较小的批量大小,您只能有效地管理它,以便在发送到服务器时总数小于数据限制。

让我们用一个例子来演示上述方法:

a)如果使用MongoDB v3.0或更低版本:

var bulk = db.test.initializeOrderedBulkOp(),
    largeArray = [{"_id":1, "foo":"bar1Upd"},{"_id":2, "foo":"bar2Upd"}],
    counter = 0;

largeArray.forEach(doc) {    
    bulk.find({ "_id": doc._id }).updateOne({ "$set": { "foo": doc.foo } });
    counter++;

    if (counter % 500 == 0) {
        bulk.execute();
        bulk = db.test.initializeOrderedBulkOp();
    }
} 

if (counter % 500 != 0 ) bulk.execute();

b)如果使用MongoDB v3.2.X或更高版本(新的MongoDB版本3.2已经deprecated Bulk() API,使用 bulkWrite() )提供了一套更新的apis:

var largeArray = [{"_id":1, "foo":"bar1Upd"},{"_id":2, "foo":"bar2Upd"}],
    bulkUpdateOps = [];

largeArray.forEach(function(doc){     
    bulkUpdateOps.push({ 
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": { "$set": { "foo": doc.foo } }
        }
    });

    if (bulkUpdateOps.length === 500) {
        db.test.bulkWrite(bulkUpdateOps);
        bulkUpdateOps = [];
    }
});         

if (bulkUpdateOps.length > 0) db.test.bulkWrite(bulkUpdateOps);