Mongo 在单个查询中批量查找和更新匹配的文档字段? [英] Mongo bulk find and update matched documents field in single query?

查看:21
本文介绍了Mongo 在单个查询中批量查找和更新匹配的文档字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个图片库,元数据存储在 mongo 中.每次网站查询匹配一定数量的存储图像时,我希望文档 shown 计数器字段递增.使用 findAndModify 对单个文档可以正常工作,但我看不到匹配多个文档并更新所有文档的好方法.

I have an image gallery with meta stored in mongo. Every time the web site query matches some number of stored images i would like the documents shown counter field to be incremented. Using findAndModify would work OK for single document but i can't see a nice way to match multiple documents and update them all.

使用最新版本的 mongo 可以吗?或者有什么推荐的最佳实践来实现这一目标?

Is this possible with latest version of mongo? Or any recommend best practices to achieve this ?

谢谢fLo

文档格式很简单

{
"name"         : "img name",
"description"  : "some more info",
"size"         : "img size in bytes",
"shown"        : "count of times the image was selected by query",
"viewed"       : "count of times the image was clicked"
}

查询是一个简单的查找,然后使用光标循环结果并使用文档ID增加显示的计数..即

And the query is a simple find, then use cursor to loop over results and bump the shown count using document id.. i.e.

db.images.update(
   { _id: "xxxx" },
   { $inc: { shown: 1 } }
)

但我不希望获得 100 个文档,然后必须遍历每个文档以单独更新.希望在单个查询中执行查找和更新.

But i would prefer not to get 100 documents then have to loop over each to update individually. Was hoping to perform find and update in single query.

推荐答案

为了提高性能,请利用 Bulk() API 用于高效地批量更新集合,因为您将操作发送到服务器批次(例如,批次大小为 500).这为您提供了更好的性能,因为您不会将每个请求都发送到服务器,而是每 500 个请求发送一次,从而使您的更新更加高效和快速.

For improved performance, take advantage of using a Bulk() API for updating the collection efficiently in bulk as you will be sending the operations to the server in batches (for example, say a batch size of 500). This gives you much better performance since you won't be sending every request to the server but just once in every 500 requests, thus making your updates more efficient and quicker.

下面演示了这种方法,第一个例子使用了Bulk() API 在 MongoDB 版本 >= 2.6 和 <3.2.它通过将 1 增加到显示的字段来更新给定数组中集合中所有匹配的文档.它假设图像数组具有以下结构

The following demonstrates this approach, the first example uses the Bulk() API available in MongoDB versions >= 2.6 and < 3.2. It updates all the matched documents in the collection from a given array by incrementing 1 to the shown field. It assumes the array of images has the structure

var images = [
    { "_id": 1, "name": "img_1.png" },
    { "_id": 2, "name": "img_2.png" }
    { "_id": 3, "name": "img_3.png" },
    ...
    { "_id": n, "name": "img_n.png" }
]

MongoDB 版本 >= 2.6 和 <3.2:

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

images.forEach(function (doc) {    
    bulk.find({ "_id": doc._id }).updateOne({ 
        "$inc": { "shown": 1 }
    });

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

下一个示例适用于新的 MongoDB 3.2 版,该版本自 已弃用 Bulk() API 并使用 bulkWrite().

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 及更高版本:

var ops = [];
images.forEach(function(doc) {
    ops.push({
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": {
                "$inc": { "shown": 1 }
            }
        }
    });

    if (ops.length === 500 ) {
        db.images.bulkWrite(ops);
        ops = [];
    }
})

if (ops.length > 0)  
    db.images.bulkWrite(ops);

这篇关于Mongo 在单个查询中批量查找和更新匹配的文档字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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