我在x的MongoDB上有这样的文档:
{
"_id" : ...
"attrs" : [
{
"key": "A1",
"type" : "T1",
"value" : "13"
},
{
"key": "A2",
"type" : "T2",
"value" : "14"
}
]
}上面的A1和A2元素只是例子:attrs字段可能包含任意数量的数组元素。
我需要从几个访问MongoDB的独立客户端并发访问MongoDB数组。例如,考虑两个客户端,一个希望将key标识为"A1“的元素的value更改为"80”,另一个希望将key标识为"A2“的元素的value更改为"20”。是否有任何使用MongoDB操作的紧凑的方法?
必须指出的是:
attr数组中的位置,只知道必须修改哪个值的元素的键。attrs数组,在客户机空间搜索要修改的元素,然后用新数组更新attrs (其中要修改的元素已经更改)将涉及竞争条件。发布于 2015-07-26 23:54:34
这里的过程非常简单,它只在要“查找或创建”数组中的元素的位置发生变化。
首先,假设每个键的元素已经到位,那么简单的情况是查询元素并使用通过$操作符返回的索引进行更新:
db.collection.update(
{
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
}
{ "$set": { "attrs.$.value": "20" }
)这只会修改匹配的元素,而不会影响其他元素。
在第二种情况下,“查找或创建”是必需的,而特定的键可能不存在,则使用“两个”update语句。但是,批量操作API允许您在对服务器的单个请求中执行此操作,只有一个响应:
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键)更新的“文档”总是一个好主意。虽然可以使用“多”更新,但您需要小心您正在做的事情。
因此,在运行“查找或创建”进程时,将不匹配的元素正确地添加到数组中,而不干扰其他元素,还以同样的方式应用先前对预期匹配的更新:
{
"_id" : ObjectId("55b570f339db998cde23369d"),
"attrs" : [
{
"key" : "A1",
"type" : "T1",
"value" : "20"
},
{
"key" : "A2",
"type" : "T2",
"value" : "14"
},
{
"key" : "A1",
"type" : "T2",
"value" : "30"
}
]
}这是一个简单的模式,当然,这里的大容量操作消除了通过向服务器发送和接收多个请求所涉及的任何开销。所有这些都不干扰其他可能存在或可能不存在的元素。
除此之外,还可以将数据保存在数组中以方便查询和分析,这是标准操作符所支持的,而无需恢复到JavaScript服务器处理以遍历元素。
https://stackoverflow.com/questions/31643054
复制相似问题