【问题标题】:multiple mongo update operator in a single statement?单个语句中的多个 mongo 更新运算符?
【发布时间】:2012-04-07 01:33:42
【问题描述】:

我可以在一个语句中结合 $pushAll 和 $inc 吗?

在合并之前,这工作正常:

db.createCollection("test");
db.test.insert({"name" : "albert", "bugs" : []});

db.test.update({"name":"albert"}, 
    {"$pushAll" : {"bugs" : [{"name":"bug1", "count":1}]}});

db.test.update({"name":"albert"}, 
    {"$inc" : {"bugs.0.count" : 1}});

db.test.update({"name":"albert"}, 
    {"$pushAll" : {"bugs" : [{"name":"bug2", "count":1}]}});

但是当我尝试像这样组合它时:

db.createCollection("test");
db.test.insert({"name" : "albert", "bugs" : []});

db.test.update({"name":"albert"}, 
    {"$pushAll" : {"bugs" : [{"name":"bug1", "count":1}]}});

db.test.update({"name":"albert"}, 
    {
       "$pushAll" : {"bugs" : [{"name":"bug2", "count":1}]}, 
       "$inc" : {"bugs.0.count" : 1}
    }
);

发生此错误:

have conflicting mods in update

我想知道是否有可能做到这一点,而且,我想结合的不仅仅是 pushAll 和 inc,但我不确定这是否受支持?


2012 年 3 月 23 日更新

我在数组的不同元素上尝试了多个 $inc,它可以工作(虽然不正确。从下面的答案中引用以阐明为什么这不起作用以及什么有效:The correct way to increment both fields is as follows: > db.test.update({"name":"albert"}, {"$inc" : {"bugs.0.count" : 1, "bugs.1.count" : 1}})

db.test.update({"name":"albert"}, 
  {
    "$inc" : {"bugs.0.count" : 1}, 
    "$inc" : {"bugs.1.count" : 1}
  }
);

$set 和 $inc 在数组的不同元素上的组合也有效:

db.test.update({"name":"albert"}, 
  {
    "$set" : {"bugs.0.test" : {"name" : "haha"}}, 
    "$inc" : {"bugs.0.count" : 1}, 
    "$inc" : {"bugs.1.count" : 1}
  }
);

但是将其中任何一个与 $push 或 $pushAll 结合起来,都会出错。

所以,我目前的结论是,问题不在于对同一数组中多个元素的多个操作,而是将这些操作与可以更改数组的 $push 或 $pushAll 结合使用是问题。

【问题讨论】:

  • 显然,同一个字段不能有两个修饰符。
  • @SergioTulentsev:我认为它们是 2 个不同的字段:“bugs”和“bugs.0.count”?
  • 好吧,我不知道。 MongoDB 可能会不这么认为:)
  • @SergioTulentsev:是的,我充满希望。非常感谢:-)

标签: mongodb


【解决方案1】:

可以对同一个文档执行多个更新,只要这些更新不冲突(因此会出现“更新中有冲突的模块”错误)。

因为 "$push" : {"bugs" : [{"name":"bug1", "count":1}]} 和 "$inc" : {"bugs.0.count" : 1} 是两者都试图修改文档的同一部分(即“bugs”数组),它们发生冲突。

如果每个更新影响文档的不同部分,则可以合并多个更新:

例如:

> db.test.drop()
true
> db.test.save({ "_id" : 1, "name" : "albert", "bugs" : [ ] })
> db.test.update({"name":"albert"}, {"$pushAll" : {"bugs" : [{"name":"bug1", "count":1}]}, "$inc" : {"increment" : 1}, $set:{"note":"Here is another field."}})
> db.test.find()
{ "_id" : 1, "bugs" : [ { "name" : "bug1", "count" : 1 } ], "increment" : 1, "name" : "albert", "note" : "Here is another field." }
> 

更新包含三个不同的操作($pushAll、$inc 和 $set),但能够成功完成,因为每个操作都会影响文档的不同部分。

我知道这并不完全是您希望做的,但希望它能让您更好地了解更新的工作原理,并可能提供一些想法,您的更新和/或文档可以如何重组以执行您的应用程序需要的功能。祝你好运。

【讨论】:

  • 谢谢马克。奇怪的巧合是,当您输入此问题的答案时,我正在 groups.google.com/group/mongodb-user/browse_thread/thread/… 阅读您的答案。无论如何,这是否意味着基本不支持对同一数组内元素的多次更新操作?如果是的话,也许有任何计划在未来得到支持?谢谢。
  • 我尝试使用 $inc 对同一个数组部分进行多次修改,并且成功了: db.test.update({"name":"albert"}, {"$inc" : {"bugs.0 .count" : 1}, "$inc" : {"bugs.1.count" : 1}});我认为这个问题只有在我将 $push 和其他操作组合在同一个数组中时才会发生?
  • 如你所见,只要更新不冲突,一个数组中的多个元素可能会同时更新。冲突来自尝试在修改数组元素之一的同时更改数组的大小。顺便说一句,您可能会注意到更新 "{"$inc" : {"bugs.0.count" : 1}, "$inc" : {"bugs.1.count" : 1}}" 不起作用正如预期的那样。 (这是因为更新文档有一个重复键“$inc”。)递增两个字段的正确方法如下: > db.test.update({"name":"albert"}, {"$inc " : {"bugs.0.count" : 1, "bugs.1.count" : 1}})
  • 哇,我没有意识到重复键“$inc”有问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多