Docs 菜单
Docs 主页
/ /

$(位置更新操作符)

$

Use the positional $ operator to identify an element in an array to update without explicitly specifying the position of the element in the array.

注意

消歧

  • 要投影或返回读取操作中的数组元素,请参阅 $ 投影操作符。

  • 如需更新数组中的所有元素,请参阅全位置操作符 $[]

  • 如要更新与数组过滤条件匹配的所有元素,请参阅过滤位置操作符 $[<identifier>]

对于在以下环境中托管的部署,可以使用位置 $ 运算符:

位置 $ 操作符采用以下形式:

{ "<array>.$" : value }

When you use update operations, such as db.collection.updateOne() and db.collection.findAndModify(), both of the following conditions must be true:

  • The positional $ operator acts as a placeholder for the first element that matches the query document.

  • The array field must appear as part of the query document.

例如:

db.collection.updateOne(
{ <array>: value ... },
{ <update operator>: { "<array>.$" : value } }
)

从 MongoDB 5.0 开始,更新操作符按字典顺序处理具有基于字符串的名称的文档字段。具有数字名称的字段按数字顺序处理。详情请参阅更新操作符行为

请勿在更新或插入(upsert)操作中使用 $操作符。如果更新查询与任何现有文档都不匹配,则更新或插入(upsert)将失败,因为 $操作符需要匹配的大量元素。

You cannot use the positional $ operator for queries that traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value.

When you use the positional $ operator with the $unset operator, the positional operator does not remove the matching element from the array. Instead, it sets the element to null.

如果查询使用否定操作符(例如 $ne$not$nin)匹配数组,则不能使用位置操作符更新该数组中的值。

You can use the positional operator if the negated portion of the query is inside an $elemMatch expression.

The positional $ update operator behaves ambiguously when you filter on multiple array fields.

When the server executes an update method, it first runs a query to determine which documents to update. If the update filters documents on multiple array fields, the positional $ update operator might not update the correct position in the array.

更多信息,请参阅示例。

Create the students collection with the following documents:

db.students.insertMany( [
{ "_id" : 1, "grades" : [ 85, 80, 80 ] },
{ "_id" : 2, "grades" : [ 88, 90, 92 ] },
{ "_id" : 3, "grades" : [ 85, 100, 90 ] }
] )

要将 grades 数组中第一个值为 80 的元素更新为 82,在不知道该元素在数组中的位置时,可使用位置 $ 操作符:

重要

您必须将数组字段包含在 query 文档中。

db.students.updateOne(
{ _id: 1, grades: 80 },
{ $set: { "grades.$" : 82 } }
)

位置 $ 操作符充当更新查询文档第一个匹配项的占位符。

操作完成后,students 集合包含以下文档:

db.students.insertMany ( [
{ _id : 1, "grades" : [ 85, 82, 80 ] },
{ _id : 2, "grades" : [ 88, 90, 92 ] },
{ _id : 3, "grades" : [ 85, 100, 90 ] }
] )

The positional $ operator allows updates to arrays that have embedded documents. Use the positional $ operator to access fields in embedded documents. Use dot notation on the $ operator.

db.collection.updateOne(
{ <query selector> },
{ <update operator>: { "array.$.field" : value } }
)

考虑下面 students 集合中的文档,其 grades 元素值是一个嵌入文档的数组:

db.students.insertOne( [
{
_id: 4,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 85, mean: 85, std: 8 }
]
}
] )

使用位置 $ 运算符来更新与“grade 等于 85 条件”相匹配的第一个数组元素的 std 字段:

重要

您必须将数组字段包含在 query 文档中。

db.students.updateOne(
{ _id: 4, "grades.grade": 85 },
{ $set: { "grades.$.std" : 6 } }
)

操作完成后,文档更新后的值如下:

{
"_id" : 4,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 8 },
{ "grade" : 85, "mean" : 90, "std" : 6 },
{ "grade" : 85, "mean" : 85, "std" : 8 }
]
}

Use the $ operator to update the first array element that matches multiple query criteria specified with the $elemMatch operator.

students 集合中的以下文档为例;其中,grades 字段值为嵌入式文档数组:

db.students.insertOne( [
{
_id: 5,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 5 },
{ grade: 90, mean: 85, std: 3 }
]
}
] )

In the following example, the $ operator updates the value of the std field in the first embedded document that has a grade field with a value less than or equal to 90 and a mean field with a value greater than 80:

db.students.updateOne(
{
_id: 5,
grades: { $elemMatch: { grade: { $lte: 90 }, mean: { $gt: 80 } } }
},
{ $set: { "grades.$.std" : 6 } }
)

此操作会更新与条件匹配的第一个嵌入式文档,即数组中的第二个嵌入式文档:

{
_id: 5,
grades: [
{ grade: 80, mean: 75, std: 8 },
{ grade: 85, mean: 90, std: 6 },
{ grade: 90, mean: 85, std: 3 }
]
}

当查询有多个数组字段用于过滤集合中的文档时,位置 $ 更新操作符就会表现得不明确。

students_deans_list 集合中的某一文档为例,其中包含学生信息数组:

db.students_deans_list.insertMany( [
{
_id: 8,
activity_ids: [ 1, 2 ],
grades: [ 90, 95 ],
deans_list: [ 2021, 2020 ]
}
] )

In the following example, the user attempts to modify the deans_list field. The example filters documents using the activity_ids, deans_list, and grades fields, and updates the 2021 value in the deans_list field to 2022:

db.students_deans_list.updateOne(
{ activity_ids: 1, grades: 95, deans_list: 2021 },
{ $set: { "deans_list.$": 2022 } }
)

When the server executes the preceding updateOne method, it filters the available documents using values in the supplied array fields. Although the deans_list field is used in the filter, it is not the field used by the positional $ update operator to determine which position in the array to update:

db.students_deans_list.find( { _id: 8 } )

示例输出:

{
_id: 8,
activity_ids: [ 1, 2 ],
grades: [ 90, 95 ],
deans_list: [ 2021, 2022 ]
}

updateOne 方法与 2021 上的 deans_list 字段匹配,但位置 $ 更新操作符却将 2020 值改为 2022。

To avoid unexpected results when matching on multiple arrays, use the filtered positional operator $[<identifier>].

提示

有关使用 $ 操作符更新数组的示例,请参阅使用 MQL 位置操作符更新文档中的数组元素。

后退

数组

在此页面上