如何在mongodb中更新多个数组元素

10 浏览
0 Comments

如何在mongodb中更新多个数组元素

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

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

文档的格式如下:

{
    "_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)

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

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

admin 更改状态以发布 2023年5月21日
0
0 Comments

更新:
从Mongo版本3.6开始,本答案不再有效,因为所提到的问题已经修复,有方法可以实现。请查看其他答案。


目前无法使用位置操作符来更新数组中的所有项。请参见JIRA http://jira.mongodb.org/browse/SERVER-1243

作为解决方法,您可以:

  • 逐个更新每个项目
    (events.0.handled events.1.handled
    ...)或...
  • 读取文档,手动编辑并保存以替换旧的文档(如果要确保原子更新,请查看"Current更新"
0
0 Comments

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

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

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

传递给 .update() 或甚至 .updateOne().updateMany().findOneAndUpdate().bulkWrite() 方法的选项中的 "arrayFilters" 指定在更新语句中给定的标识符上匹配的条件。任何匹配条件的元素都将被更新。

需注意,问题中给出的 "multi" 在预期中使用是为了"更新多个元素",但这不是也仍然不是该情况。它在这里的使用适用于 "多个文档",一直是这样,或现在在现代 API 版本中以强制设置为 .updateMany()

注意 有些讽刺的是,虽然.update()和类似方法中的"选项"参数指定了这个语法,但这个语法通常与最近版本的驱动程序兼容。

然而,mongo shell就不是这样了,因为它的实现方式("具有讽刺意味的是,为了向后兼容")不识别并移除arrayFilters参数,通过解析选项以向先前的MongoDB服务器版本提供"向后兼容性"和"遗留"的.update() API调用语法。

因此,如果您想在mongo shell或其他"基于shell"的产品(特别是Robo 3T)中使用该命令,您需要获得开发分支或版本发布的最新版本,版本需要是3.6或更高版本。

参见位置加全部$[],它也可以更新"多个数组元素",但不适用于指定的条件,并适用于数组中的所有元素,如果需要这个操作。

还可以参见使用MongoDB更新嵌套数组,了解这些新的位置操作符如何应用于"嵌套"数组结构,其中"数组在其他数组中"。

重要 - 从以前版本升级的安装可能没有启用MongoDB功能,这也可能导致语句失败。您应该确保您的升级过程已经完成详细的任务,例如索引升级,然后运行

   db.adminCommand( { setFeatureCompatibilityVersion: "3.6" } )

或是适用于您安装版本的更高版本。例如,当前版本4及以后版本的"4.0"。这使得新的位置更新操作符和其他功能成为可能。您也可以使用以下方式进行检查:

   db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } )

返回当前设置

0