在文档中更新数组
概述
在本指南中,您可以学习如何使用以下数组更新运算符来修改文档中嵌入的数组
有关数组更新运算符的列表,请参阅服务器手册文档中的更新运算符。
指定数组元素
位置操作符用于指定要更新的数组元素。您可以使用这些操作符对数组的第一元素、所有元素或满足特定条件的元素进行更新。
使用位置操作符指定数组中的元素,请使用点表示法。点表示法是用于导航BSON对象的属性访问语法。有关更多信息,请参阅点表示法。
第一个匹配的数组元素
要更新符合查询条件的每个文档的第一个数组元素,请使用位置操作符 $
。
位置操作符 $
引用由查询匹配的数组。您不能使用此操作符来引用嵌套数组。如果需要访问嵌套数组,请使用过滤位置操作符。
重要
不要在 upsert
调用中使用 $
操作符,因为驱动程序将 $
视为插入文档中的字段名。
示例
此示例使用以下示例文档来显示如何更新第一个匹配的数组元素
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 100 }, { x: "goodbye", y: 1000 } ] }
以下代码显示了如何增加符合查询的第一个数组元素的值。
查询匹配 entries
数组中的元素,其中 x
的值为 string
类型。更新在第一个匹配元素中将 y
值增加 33
。
// Query for all elements in entries array where the value of x is a string const query = { "entries.x": { $type : "string" } }; // On first matched element, increase value of y by 33 const updateDocument = { $inc: { "entries.$.y": 33 } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
运行更新操作后,文档将类似于以下内容
{ _id: ..., entries: [ { x: false, y: 1 }, { x: "hello", y: 133 }, { x: "goodbye", y: 1000 } ] }
示例中在查询中包含了 entries.x
字段,以匹配 $
操作符应用更新操作的数组。如果您在使用 $
操作符进行更新时省略了 entries.x
字段,则驱动程序无法识别匹配的数组并引发以下错误
MongoServerError: The positional operator did not find the match needed from the query.
匹配所有数组元素
要更新匹配您查询的每个文档的所有数组元素,请使用所有位置操作符 $[]
。
示例
以下示例使用以下示例文档,这些文档描述了电话记录,以展示如何更新所有匹配的数组元素
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom", duration: 67 }, { time: "04:11 PM", caller: "Dad", duration: 121 }, { time: "06:36 PM", caller: "Grandpa", duration: 13 } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
以下代码展示了如何从日期为 "5/15/2023"
的文档中删除 calls
数组中所有条目的 duration
字段
// Query for all documents where date is the string "5/15/2023" const query = { date: "5/15/2023" }; // For each matched document, remove duration field from all entries in calls array const updateDocument = { $unset: { "calls.$[].duration": "" } }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument);
运行更新操作后,文档将类似于以下内容
{ _id: ..., date: "5/15/2023", calls: [ { time: "10:08 AM", caller: "Mom" }, { time: "04:11 PM", caller: "Dad" }, { time: "06:36 PM", caller: "Grandpa" } ] }, { _id: ..., date: "5/16/2023", calls: [ { time: "11:47 AM", caller: "Mom", duration: 4 }, ] }
匹配多个数组元素
要对匹配查询的每个文档的所有嵌入数组元素执行更新,请使用过滤位置操作符 $[<identifier>]
。
过滤位置操作符 $[<identifier>]
指定更新文档中匹配的数组元素。要标识要匹配的数组元素,请将此操作符与 <identifier>
配对,在 arrayFilters
对象中使用。
<identifier>
占位符表示数组字段的元素。您必须为 <identifier>
选择一个以小写字母开头且只包含字母数字字符的值。
用法
您可以在更新操作中使用过滤位置操作符。更新操作接受查询、更新文档和可选的选项对象作为参数。
以下步骤描述了如何在更新操作中使用过滤位置操作符
按照以下格式格式化您的更新文档
{ $<operator>: { "<array>.$[<identifier>].<arrayField>": <updateParameter> } } 此更新文档包含以下占位符
$<operator>
:数组更新操作符<array>
:要更新的文档中的数组<identifier>
:过滤位置操作符的标识符<arrayField>
:要更新的<array>
数组元素的字段<updateParameter>
:描述更新的值
在
arrayFilters
对象中添加匹配条件。此对象是一个查询数组,指定哪些数组元素应包含在更新中。在options
参数中设置此对象arrayFilters: [ { "<identifier>.<arrayField1>": <updateParameter1> }, { "<identifier>.<arrayField2>": <updateParameter2> }, ... ] 将查询、更新文档和选项传递给更新方法。以下示例代码显示了如何使用这些参数调用
updateOne()
方法await myColl.updateOne(query, updateDocument, options);
示例
此示例使用以下示例文档(描述特定食谱的购物清单)来展示如何更新某些匹配的数组元素
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 3, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 1, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }
假设您想增加您在 "11/12/2023"
购物之旅中为食谱购买的商品数量。如果项目满足以下所有条件,则将其数量加倍
该商品是为
"Fried rice"
食谱的。项目名称不包含单词
"油"
。
要将匹配数组条目的数量
值加倍,请使用以下代码中所示的过滤位置运算符
// Query for all documents where date is the string "11/12/2023" const query = { date: "11/12/2023" }; // For each matched document, change the quantity of items to 2 const updateDocument = { $mul: { "items.$[i].quantity": 2 } }; // Update only non-oil items used for fried rice const options = { arrayFilters: [ { "i.recipe": "Fried rice", "i.item": { $not: { $regex: "oil" } }, } ] }; // Execute the update operation const result = await myColl.updateOne(query, updateDocument, options);
更新操作将匹配条件的项目的数量
值乘以2
。项目"芝麻油"
在arrayFilters
对象中不符合条件,因此被排除在更新之外。以下文档反映了这些更改
{ _id: ..., date: "11/12/2023", items: [ { item: "Scallions", quantity: 6, recipe: "Fried rice" }, { item: "Mangos", quantity: 4, recipe: "Salsa" }, { item: "Pork shoulder", quantity: 2, recipe: "Fried rice" }, { item: "Sesame oil", quantity: 1, recipe: "Fried rice" } ] }, { _id: ..., date: "11/20/2023", items: [ { item: "Coffee beans", quantity: 1, recipe: "Coffee" } ] }