假设我们有以下集合,我有几个问题:
{
"_id" : ObjectId("4faaba123412d654fe83hg876"),
"user_id" : 123456,
"total" : 100,
"items" : [
{
"item_name" : "my_item_one",
"price" : 20
},
{
"item_name" : "my_item_two",
"price" : 50
},
{
"item_name" : "my_item_three",
"price" : 30
}
]
}
1.我想增加“item_name”:“my_item_two”的价格,如果它不存在,它应该被追加到“items”数组中。
1.如何同时更新两个字段?例如,增加“my_item_three”的价格,同时增加“total”(具有相同的值)。
我更喜欢在MongoDB端执行此操作,否则我必须在客户端(Python)加载文档并构造更新的文档,然后将其替换为MongoDB中的现有文档。
这是我已经尝试过的,如果**对象存在,效果很好:
db.test_invoice.update({user_id : 123456 , "items.item_name":"my_item_one"} , {$inc: {"items.$.price": 10}})
但是,如果密钥不存在,它什么也不做。此外,它仅更新嵌套对象。使用此命令无法同时更新“total”字段。
4条答案
按热度按时间0dxa2lsx1#
对于问题#1,让我们把它分成两部分。首先,递增“items.item_name”等于“my_item_two”的任何文档。为此,您必须使用位置“$”运算符。类似于:
请注意,这只会增加任何数组中第一个匹配的子文档(因此,如果数组中有另一个文档的“item_name”等于“my_item_two”,它不会增加)。但这可能是你想要的。
第二部分比较棘手。我们可以将一个新项推送到一个没有“my_item_two”的数组中,如下所示:
对于你的问题#2,答案更简单。要在任何包含“my_item_three”的文档中增加total和item_three的价格,您可以同时在多个字段上使用$inc运算符。类似于:
5gfr0r5j2#
没有办法在单个查询中做到这一点。您必须在第一个查询中搜索文档:
如果文件存在:
其他
无需添加条件
{$ne : "my_item_two" }
。同样在多线程环境中,你必须小心,一次只能有一个线程执行第二个(插入情况,如果文档没有找到),否则重复的嵌入文档将被插入。
mw3dktmi3#
我们可以使用**
$set
**操作符来更新对象字段内的嵌套数组更新值h6my8fg24#
确保“item_name”字段没有重复的一种方法是执行与问题#1的答案https://stackoverflow.com/a/10523963中给出的相同操作,但顺序相反!
1.如果“items.item_name”:{"$ne”:“my_name”} -更新过滤器必须包含一些唯一索引的字段,则推入文档!”“假的,假的。
1.如果“items.item_name”:“my_name”,则递增文档。
第一次更新应该是原子的,因此如果数组已经包含item_name为“my_name”的元素,它不会做任何事情。
到第二次更新发生时,必须有一个带有“item_name”=“my_name”的数组元素