我有一个Mongo文档,其中包含一个元素数组。

我想重置.profile = XX数组中所有对象的.handled属性。

文件格式如下:

{
    "_id": ObjectId("4d2d8deff4e6c1d71fc29a07"),
    "user_id": "714638ba-2e08-2168-2b99-00002f3d43c0",
    "events": [{
            "handled": 1,
            "profile": 10,
            "data": "....."
        } {
            "handled": 1,
            "profile": 10,
            "data": "....."
        } {
            "handled": 1,
            "profile": 20,
            "data": "....."
        }
        ...
    ]
}

所以,我尝试了以下方法:

.update({"events.profile":10},{$set:{"events.$.handled":0}},false,true)

但是,它只更新每个文档中第一个匹配的数组元素。(这是$ -位置操作符的定义行为。)

如何更新所有匹配的数组元素?


当前回答

在mongodb中更新多个文档中的数组字段。

使用$pull或$push和update many query来更新mongoDb中的数组元素。

Notification.updateMany(
    { "_id": { $in: req.body.notificationIds } },
    {
        $pull: { "receiversId": req.body.userId }
    }, function (err) {
        if (err) {
            res.status(500).json({ "msg": err });
        } else {
            res.status(200).json({
                "msg": "Notification Deleted Successfully."
            });
        }
    });

其他回答

更新: 从Mongo 3.6版开始,这个答案不再有效,因为上面提到的问题已经修复,有办法实现这一点。请检查其他答案。


此时,不可能使用位置操作符来更新数组中的所有项。参见JIRA http://jira.mongodb.org/browse/SERVER-1243

作为一份工作,你可以:

单独更新每个项目 (events.0。处理events.1.handled )或… 阅读文件,进行编辑 手动保存并替换 旧版本(勾选“如果更新 如果你想确保“当前” 原子更新)

这个帖子很老了,但我来这里寻找答案,因此提供了新的解决方案。

在MongoDB 3.6+版本中,现在可以使用位置操作符更新数组中的所有项。点击这里查看官方文件。

下面的问题将适用于这里提出的问题。我也用Java-MongoDB驱动进行了验证,工作成功。

.update(   // or updateMany directly, removing the flag for 'multi'
   {"events.profile":10},
   {$set:{"events.$[].handled":0}},  // notice the empty brackets after '$' opearor
   false,
   true
)

希望这能帮助到像我这样的人。

$[]操作符选择所有嵌套数组。使用'$[]'可以更新所有数组项

.update({"events.profile":10},{$set:{"events.$[].handled":0}},false,true)

参考

在mongodb中更新多个文档中的数组字段。

使用$pull或$push和update many query来更新mongoDb中的数组元素。

Notification.updateMany(
    { "_id": { $in: req.body.notificationIds } },
    {
        $pull: { "receiversId": req.body.userId }
    }, function (err) {
        if (err) {
            res.status(500).json({ "msg": err });
        } else {
            res.status(200).json({
                "msg": "Notification Deleted Successfully."
            });
        }
    });

随着MongoDB 3.6的发布(在MongoDB 3.5.12的开发分支中可用),您现在可以在一个请求中更新多个数组元素。

这使用了在这个版本中引入的过滤位置$[<identifier>]更新操作符语法:

db.collection.update(
  { "events.profile":10 },
  { "$set": { "events.$[elem].handled": 0 } },
  { "arrayFilters": [{ "elem.profile": 10 }], "multi": true }
)

"arrayFilters"被传递给.update()或甚至 . updateone (), . updatemany (), . findoneandupdate()或. bulkwrite()方法指定更新语句中给定的标识符要匹配的条件。任何匹配给定条件的元素都将被更新。

注意到问题上下文中所给出的“multi”是在期望这将“更新多个元素”的情况下使用的,但事实并非如此,而且仍然不是如此。它在这里的用法适用于“多个文档”,就像一直以来的情况一样,或者现在在现代API版本中指定为. updatemany()的强制设置。

NOTE Somewhat ironically, since this is specified in the "options" argument for .update() and like methods, the syntax is generally compatible with all recent release driver versions. However this is not true of the mongo shell, since the way the method is implemented there ( "ironically for backward compatibility" ) the arrayFilters argument is not recognized and removed by an internal method that parses the options in order to deliver "backward compatibility" with prior MongoDB server versions and a "legacy" .update() API call syntax. So if you want to use the command in the mongo shell or other "shell based" products ( notably Robo 3T ) you need a latest version from either the development branch or production release as of 3.6 or greater.

另参见positional all $[],它也更新“多个数组元素”,但不应用于指定的条件,并应用于数组中的所有元素,其中这是所需的操作。

另请参见用MongoDB更新嵌套数组,了解这些新的位置操作符如何应用于“嵌套”数组结构,其中“数组在其他数组中”。

IMPORTANT - Upgraded installations from previous versions "may" have not enabled MongoDB features, which can also cause statements to fail. You should ensure your upgrade procedure is complete with details such as index upgrades and then run db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } ) Or higher version as is applicable to your installed version. i.e "4.0" for version 4 and onwards at present. This enabled such features as the new positional update operators and others. You can also check with: db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } ) To return the current setting