首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MongoDB中嵌入文档的数组元素的并发更新

MongoDB中嵌入文档的数组元素的并发更新
EN

Stack Overflow用户
提问于 2015-07-26 23:35:34
回答 1查看 1.3K关注 0票数 1

我在x的MongoDB上有这样的文档:

代码语言:javascript
复制
{
    "_id" : ...
    "attrs" : [
        {
            "key": "A1",
            "type" : "T1",
            "value" : "13"
        },
        {
            "key": "A2",
            "type" : "T2",
            "value" : "14"
        }
    ]
}

上面的A1A2元素只是例子:attrs字段可能包含任意数量的数组元素。

我需要从几个访问MongoDB的独立客户端并发访问MongoDB数组。例如,考虑两个客户端,一个希望将key标识为"A1“的元素的value更改为"80”,另一个希望将key标识为"A2“的元素的value更改为"20”。是否有任何使用MongoDB操作的紧凑的方法?

必须指出的是:

  • 客户端不知道每个元素在attr数组中的位置,只知道必须修改哪个值的元素的键。
  • 在客户机空间中读取整个attrs数组,在客户机空间搜索要修改的元素,然后用新数组更新attrs (其中要修改的元素已经更改)将涉及竞争条件。
  • 客户端还可以添加和删除数组中的元素。因此,在MongoDB上进行第一次搜索以定位要修改的元素的位置,然后使用该特定位置进行更新通常是不起作用的,因为元素可能已经添加/删除,从而改变了以前找到的位置。
EN

回答 1

Stack Overflow用户

发布于 2015-07-26 23:54:34

这里的过程非常简单,它只在要“查找或创建”数组中的元素的位置发生变化。

首先,假设每个键的元素已经到位,那么简单的情况是查询元素并使用通过$操作符返回的索引进行更新:

代码语言:javascript
复制
db.collection.update(
   {
       "_id": docId, 
       "attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
   }
   { "$set": { "attrs.$.value": "20" }
)

这只会修改匹配的元素,而不会影响其他元素。

在第二种情况下,“查找或创建”是必需的,而特定的键可能不存在,则使用“两个”update语句。但是,批量操作API允许您在对服务器的单个请求中执行此操作,只有一个响应:

代码语言:javascript
复制
var bulk = db.collection.initializeOrderedBulkOp();

// Try to update where exists
bulk.find({
    "_id": docId,
    "attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
    "$set": { "attrs.$.value": "30" }
});

// Try to add where does noes not exist
bulk.find({
    "_id": docId,
    "attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
    "$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});

bulk.execute();

基本的逻辑是,首先进行更新尝试,将元素与所需的值匹配,就像前面所做的那样。通过使用$not反转匹配逻辑,其他条件测试根本找不到元素的位置。

在没有找到数组元素的情况下,通过$push添加一个新元素是有效的。

我确实应该补充一点,因为我们在这里专门寻找负面匹配,所以匹配您打算通过某些唯一标识符(如_id键)更新的“文档”总是一个好主意。虽然可以使用“多”更新,但您需要小心您正在做的事情。

因此,在运行“查找或创建”进程时,将不匹配的元素正确地添加到数组中,而不干扰其他元素,还以同样的方式应用先前对预期匹配的更新:

代码语言:javascript
复制
{
    "_id" : ObjectId("55b570f339db998cde23369d"),
    "attrs" : [
            {
                    "key" : "A1",
                    "type" : "T1",
                    "value" : "20"
            },
            {
                    "key" : "A2",
                    "type" : "T2",
                    "value" : "14"
            },
            {
                    "key" : "A1",
                    "type" : "T2",
                    "value" : "30"
            }
    ]
}

这是一个简单的模式,当然,这里的大容量操作消除了通过向服务器发送和接收多个请求所涉及的任何开销。所有这些都不干扰其他可能存在或可能不存在的元素。

除此之外,还可以将数据保存在数组中以方便查询和分析,这是标准操作符所支持的,而无需恢复到JavaScript服务器处理以遍历元素。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31643054

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档