$[<标识符>]
在本页
定义
$[<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开始,更新运算符按字典顺序处理基于字符串命名的字段。具有数字名称的字段按数字顺序处理。有关详细信息,请参阅更新运算符行为。
限制
选项 arrayFilters
不能包括以下查询运算符
upsert
如果upsert操作导致插入,则查询必须包含对数组字段的精确匹配,以便在更新语句中使用$[<标识符>]
。
例如,以下upsert操作,在更新文档中使用$[<identifier>]
,指定了一个数组字段的精确相等匹配条件
db.collection.updateOne( { myArray: [ 0, 1 ] }, { $set: { "myArray.$[element]": 2 } }, { arrayFilters: [ { element: 0 } ], upsert: true } )
如果不存在这样的文档,该操作将插入一个类似于以下文档的文档
{ "_id" : ObjectId(...), "myArray" : [ 2, 1 ] }
如果upsert操作没有包含精确相等匹配,并且找不到匹配的文档来更新,则upsert操作会出错。例如,如果在更新时找不到匹配的文档,以下操作将出错
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>]
可用于查询,这些查询跨越多个数组以及嵌套数组。
例如,请参阅使用$[]
联合更新嵌套数组。
示例
更新所有匹配arrayFilters
的数组元素
创建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 ] }
更新数组中所有匹配 arrayFilters
的文档
$[<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
数组中所有既大于或等于 80
又大于或等于 5
的 std
字段的值,请使用位置 $[<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.questions
数组中更新大于或等于 8
的值,前提是相关 grades.type
字段为 quiz
。
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 } } ] } )