使用MongoDB将标识符用于$ []中对象的索引

问题描述 投票:1回答:1

假设我有此文档:

docs: [
  {
    a: "a"
    b: "b"
  },
  {
    a: "a"
    b: "b"
  },
  {
    a: "a"
    b: "b"
  }
]

我需要获得此收藏集:

docs: [
  {
    a: "a"
    b: "b"
  },
  {
    a: "a"
    b: "c"
  },
  {
    a: "a"
    b: "c"
  }
]

如何定义使用$ []和跳过第一个文档并更改其他文档的arrayFilters?

db.collection("aaa").update(
  {<query>},
  {$set: {"docs.$[v].b": "c"}},
  {arrayFilters: [{"v": {$not: 0}, "v.a": "a"}],
})
mongodb mongodb-query aggregation-framework
1个回答
0
投票

作为MongoDB版本> = 4.2.update()操作中接受聚合管道。您可以使用以下查询进行此操作:

查询:

db.getCollection("collectionName").update(
 {<your filter part plus> , docs: { $exists: true, $ne: [] }}, // checks for `docs` not to be empty or not exists.
 [
  {
    $set: {
      docs: {
        $concatArrays: [
          [{ $arrayElemAt: ["$docs", 0] }],
          {
            $map: {
              input: { $slice: ["$docs", 1, { $size: "$docs" }] },
              in: { $cond: [ { $eq: [ "$$this.a", "a" ] }, { $mergeObjects: ["$$this", { b: "c" }] } , "$$this" ] } // Conditional check to return same object or updated object.
            }
          }
        ]
      }
    }
  }
])

Test:在此处验证聚合管道:mongoplayground

Ref: aggregation-pipeline

说明: $set是聚合的$addFields的别名,如果存在该字段,它将重新创建该字段,或者将创建一个具有指定名称的新字段。最后,将使用新数组重新创建docs字段。我们将一个数组作为input传递给$map运算符,此输入数组将大部分是整个原始docs数组,但没有第一个元素。因此,$map将重新创建一个新数组,该数组将与array converted first element串联(对于$concatArrays,两个args都应为数组,因此,我们拉出$docs数组的第一个对象,并用[]包装)它是docs数组的数组。 $mergeObjects仅将b数组的每个对象内的docs字段替换为{ b: "c" },但对象中的所有其他字段将保持不变。

© www.soinside.com 2019 - 2024. All rights reserved.