Docs 菜单
Docs 主页
/
MongoDB Manual
/ / / /

$[<identifier>]

在此页面上

  • 定义
  • 行为
  • 限制
  • upsert
  • 嵌套数组
  • 示例
  • 更新所有匹配的数组元素 arrayFilters
  • 更新数组中与 arrayFilters 匹配的所有文档
  • 更新匹配多个条件的所有数组元素
  • 使用否定运算符更新数组元素
  • 更新嵌套数组 $[]
$[<identifier>]

过滤位置操作符 $[<identifier>] 用于识别匹配更新操作 arrayFilters 条件的数组元素,例如 db.collection.updateMany()db.collection.findAndModify()

arrayFilters 选项一起使用时,$[<identifier>] 操作符的形式如下:

{ <update operator>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } ] }

arrayFilters 选项结合使用,可更新一个或多个与查询条件匹配的文档中与 arrayFilters 条件匹配的所有元素。示例:

db.collection.updateMany(
{ <query conditions> },
{ <update operator>: { "<array>.$[<identifier>]" : value } },
{ arrayFilters: [ { <identifier>: <condition> } ] }
)

注意

<identifier> 必须以小写字母开头,且只能包含字母数字字符。

有关示例,请参阅更新匹配 arrayFilters 的所有数组元素

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

The arrayFilters 选项不能包含以下查询运算符:

  • $expr

  • $text

  • $where

如果更新插入 (upsert) 操作触发插入,query 则须包含针对该数组字段的完全相等匹配项,以便在更新语句中使用 $[<identifier>]

例如,以下 upsert 操作将在更新文档中使用 $[<identifier>] 来指定针对该数组字段的完全相等匹配条件:

db.collection.updateOne(
{ myArray: [ 0, 1 ] },
{ $set: { "myArray.$[element]": 2 } },
{ arrayFilters: [ { element: 0 } ], upsert: true }
)

如果不存在此类文档,则该操作将导致插入类似于以下形式的文档:

{ "_id" : ObjectId(...), "myArray" : [ 2, 1 ] }

如果更新或插入操作不包括完全相等匹配,也没有找到匹配的文档进行更新,更新或插入操作就会出错。例如,如果找不到匹配的文档进行更新,以下操作就会出错:

db.array.updateOne(
{ },
{ $set: { "myArray.$[element]": 10 } },
{ arrayFilters: [ { element: 9 } ], upsert: true }
)

该操作将返回类似下面的错误:

MongoServerError: The path 'myArray' must exist in the document in order to apply array updates.

过滤位置操作符 $[<identifier>] 可用于遍历多个数组和嵌套数组的查询。

有关示例,请参阅搭配使用 $[] 以更新嵌套数组

创建 students 集合:

db.students.insertMany( [
{ "_id" : 1, "grades" : [ 95, 92, 90 ] },
{ "_id" : 2, "grades" : [ 98, 100, 102 ] },
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }
] )

要更新 grades 数组中大于或等于 100 的所有元素,请使用带有 arrayFilters 的过滤位置操作符 $[<identifier>]

db.students.updateMany(
{ },
{ $set: { "grades.$[element]" : 100 } },
{ arrayFilters: [ { "element": { $gte: 100 } } ] }
)

位置 $[<identifier>] 操作符充当数组字段中与 arrayFilters 中指定条件相匹配的所有元素的占位符。

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

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 100 ] }
{ "_id" : 3, "grades" : [ 95, 100, 100 ] }

$[<identifier>] 操作符便于更新包含嵌入式文档的数组。要访问嵌入式文档中的字段,请使用带 $[<identifier>]点表示法

db.collection.updateMany(
{ <query selector> },
{ <update operator>: { "array.$[<identifier>].field" : value } },
{ arrayFilters: [ { <identifier>: <condition> } } ] }
)

创建 students2 集合:

db.students2.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 90, "std" : 4 },
{ "grade" : 85, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 75, "std" : 6 },
{ "grade" : 87, "mean" : 90, "std" : 3 },
{ "grade" : 85, "mean" : 85, "std" : 4 }
]
}
] )

要修改 grades 数组中成绩大于或等于 85 的所有元素的 mean 字段的值,请使用位置 $[<identifier>] 操作符和 arrayFilters

db.students2.updateMany(
{ },
{ $set: { "grades.$[elem].mean" : 100 } },
{ arrayFilters: [ { "elem.grade": { $gte: 85 } } ] }
)

操作完成后,集合有以下文档:

{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 100, "std" : 6 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}

创建 students3 集合:

db.students3.insertMany( [
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 100, "std" : 6 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}
] )

如需修改 grades 数组中所有元素的 std 字段的值,其中等级均大于或等于 80,且 std 大于或等于 5,请使用位置 $[<identifier>] 操作符和 arrayFilters

db.students3.updateMany(
{ },
{ $inc: { "grades.$[elem].std" : -1 } },
{ arrayFilters: [ { "elem.grade": { $gte: 80 }, "elem.std": { $gte: 5 } } ] }
)

操作完成后,集合有以下文档:

{ "_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 5 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 5 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 100, "std" : 5 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}

创建 alumni 集合:

db.alumni.insertMany( [
{
"_id": 1,
"name": "Christine Franklin",
"degrees": [
{ "level": "Master" },
{ "level": "Bachelor" }
],
},
{
"_id": 2,
"name": "Reyansh Sengupta",
"degrees": [ { "level": "Bachelor" } ],
}
] )

要修改 degrees 数组中所有没有 "level": "Bachelor" 的元素,请使用位置 $[<identifier>] 操作符和 $ne 查询操作符:

db.alumni.updateMany(
{ },
{ $set : { "degrees.$[degree].gradcampaign" : 1 } },
{ arrayFilters : [ {"degree.level" : { $ne: "Bachelor" } } ] }
)

操作完成后,集合有以下文档:

{
_id: 1,
name: 'Christine Franklin',
degrees: [
{ level: 'Master', gradcampaign: 1 },
{ level: 'Bachelor' }
]
},
{
_id: 2,
name: 'Reyansh Sengupta',
degrees: [ { level: 'Bachelor' } ]
}

$[<identifier>] 过滤位置操作符与 $[] 全位置操作符结合使用,可用于更新嵌套数组。

使用以下文档创建一个集合 students4

db.students4.insertOne(
{ "_id" : 1,
"grades" : [
{ type: "quiz", questions: [ 10, 8, 5 ] },
{ type: "quiz", questions: [ 8, 9, 6 ] },
{ type: "hw", questions: [ 5, 4, 3 ] },
{ type: "exam", questions: [ 25, 10, 23, 0 ] },
]
}
)

如果关联的 grades.type 字段为 quiz,以下代码则会更新嵌套 grades.questions 数组中大于或等于 8 的值。

db.students4.updateMany(
{},
{ $inc: { "grades.$[t].questions.$[score]": 2 } },
{ arrayFilters: [ { "t.type": "quiz" }, { "score": { $gte: 8 } } ] }
)

注意

不要在数组标识符两边添加空格。如果您在上一示例中使用 grades.$[ t ].questions.$[ score ] ,该示例将失败。

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

{
"_id" : 1,
"grades" : [
{ "type" : "quiz", "questions" : [ 12, 10, 5 ] },
{ "type" : "quiz", "questions" : [ 10, 11, 6 ] },
{ "type" : "hw", "questions" : [ 5, 4, 3 ] },
{ "type" : "exam", "questions" : [ 25, 10, 23, 0 ] }
]
}

要更新 grades.questions 嵌套数组中所有大于或等于 8 的值,而无论 type 为何,请执行以下操作:

db.students4.updateMany(
{},
{ $inc: { "grades.$[].questions.$[score]": 2 } },
{ arrayFilters: [ { "score": { $gte: 8 } } ] }
)

提示

另请参阅:

后退

$[]