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

查看:81
本文介绍了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.

推荐答案

为提高性能,请充分利用

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,并使用

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天全站免登陆