$[<identifier>]

在本页面

Definition

  • $[<identifier>]
    {#up.S[<identifier>]}
    • 3.6 版的新功能。

过滤后的位置运算符$[<identifier>]标识与arrayFilters条件匹配的数组元素,以进行更新操作,例如db.collection.update()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> } ] }
)

Note

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

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

Behavior

upsert

如果upsert操作导致插入,则query必须在数组字段上包含完全相等的 match才能在更新语句中使用$[<identifier>]

例如,下面的更新操作在更新文档中使用$[<identifier>],它在数组字段上指定完全相等的匹配条件:

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

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

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

如果 upsert 操作不包括完全相等的匹配项,并且找不到匹配的文档要更新,则 upsert 操作将出错。例如,如果找不到匹配的文档来更新,则以下操作将出错:

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

该操作将返回类似于以下内容的错误:

WriteResult({
   "nMatched" : 0,
   "nUpserted" : 0,
   "nModified" : 0,
   "writeError" : {
      "code" : 2,
      "errmsg" : "The path 'myArray' must exist in the document in order to apply array updates."
   }
})

Nested Arrays

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

有关示例,请参见与$ []联合更新嵌套数组

Examples

更新所有与 arrayFilters 匹配的数组元素

考虑包含以下文档的集合students

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

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

db.students.update(
   { },
   { $set: { "grades.$[element]" : 100 } },
   { multi: true,
     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 ] }

更新与数组中的 arrayFilter 匹配的所有文档

$[<identifier>]运算符有助于更新包含嵌入式文档的数组。要访问嵌入文档中的字段,请使用$[<identifier>]上的dot notation

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

考虑包含以下文档的集合students2

{
   "_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.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     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 }
   ]
}

更新匹配多个条件的所有数组元素

考虑包含以下文档的集合students2

{
   "_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数组中所有等级大于或等于80std大于或等于5的所有元素修改std字段的值,请使用位置$[<identifier>]运算符和arrayFilters

db.students2.update(
   { },
   { $inc: { "grades.$[elem].std" : -1 } },
   { arrayFilters: [ { "elem.grade": { $gte: 80 }, "elem.std": { $gt: 5 } } ], multi: true }
)

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

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

{
   "_id": 1,
   "name": "Christine Franklin",
   "degrees": [
      { "level": "Master",
        "major": "Biology",
        "completion_year": 2010,
        "faculty": "Science"
      },
      {
        "level": "Bachelor",
        "major": "Biology",
        "completion_year": 2008,
        "faculty": "Science"
      }
   ],
   "school_email": "cfranklin@example.edu",
   "email": "christine@example.com"
}
{
   "_id": 2,
   "name": "Reyansh Sengupta",
   "degrees": [
      { "level": "Bachelor",
        "major": "Chemical Engineering",
        "completion_year": 2002,
        "faculty": "Engineering"
      }
   ],
   "school_email": "rsengupta2@example.edu"
}

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

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

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

{
   "_id" : 1,
   "name" : "Christine Franklin",
   "degrees" : [
      {
         "level" : "Master",
         "major" : "Biology",
         "completion_year" : 2010,
         "faculty" : "Science",
         "gradcampaign" : 1
      },
      {
         "level" : "Bachelor",
         "major" : "Biology",
         "completion_year" : 2008,
         "faculty" : "Science"
      }
   ],
   "school_email" : "cfranklin@example.edu",
   "email" : "christine@example.com"
}
{
   "_id" : 2,
   "name" : "Reyansh Sengupta",
   "degrees" : [
      {
         "level" : "Bachelor",
         "major" : "Chemical Engineering",
         "completion_year" : 2002,
         "faculty" : "Engineering"
      }
   ],
   "school_email" : "rsengupta2@example.edu"
}

与$ []联合更新嵌套数组

$[<identifier>]过滤后的位置运算符与$[]所有位置运算符一起可用于更新嵌套数组。

创建包含以下文档的集合students3

db.students3.insert([
   { "_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.students3.update(
   {},
   { $inc: { "grades.$[t].questions.$[score]": 2 } },
   { arrayFilters: [ { "t.type": "quiz" } , { "score": { $gte: 8 } } ], multi: true}
)

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

{
   "_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.students3.update(
   {},
   { $inc: { "grades.$[].questions.$[score]": 2 } },
   { arrayFilters: [  { "score": { $gte: 8 } } ], multi: true}
)