【问题标题】:What's the best way to update multiple values in an array of documents using MongoDB?使用 MongoDB 更新文档数组中的多个值的最佳方法是什么?
【发布时间】:2021-10-20 11:18:52
【问题描述】:

所以我在数据库中有一个文档,看起来像这样:

...
someArray: [{
id: string
qty: number
}]
...

数据库查询需要更新这个单个文档,并为数组中符合某些条件的条目增加“数量”字段的值。

我知道我可以通过多种方式做到这一点,一个(arrayFilters)或多个查询等。但我需要满足以下要求:

  • 在我的更新运行时,其他更新操作不得修改此文档。我的理解是,只要我将其作为单个操作(原子更新)执行,MongoDB 4.4 就已经保证了这一点。对吗?

  • 每个匹配值都必须更新,否则它们都不应该更新。因此,如果我只能更新数组的 2 个元素并且因为条件失败而没有更新第 3 个元素,我需要还原整个操作。

最好的方法是什么?

我的意思是,事务在这里没有用,因为我只更新一个文档。 此外,如果更新条件失败,这不是错误,因此事务不会恢复。

另一方面,如果我使用多个更新操作来执行此操作,那么另一个更新(由另一个用户启动)可能会修改记录并且我无法恢复。

有没有更好的方法来做到这一点?

提前致谢!

【问题讨论】:

    标签: arrays mongodb


    【解决方案1】:

    对 1 个文档的更新操作始终是原子操作。

    Mongodb 4.0+ 添加了多文档操作的事务,这里不需要。

    MongoDB 4.2 增加了管道更新,有了这些我们可以进行非常复杂的更新。但是我们不能将更新操作符与聚合操作符混合使用,您应该使用聚合操作符和阶段。

    在您的情况下,$map 操作员可能会做得很好,它会为数组的每个成员运行检查这些条件并生成更新的成员。

    Example1, members are numbers

    它只是一个数组 [1,2,3],如果 member>=3 则变为“已更新!”

    db.collection.update({
      "_id": {
        "$eq": 1
      }
    },
    [
      {
        "$addFields": {
          "myarray": {
            "$map": {
              "input": "$myarray",
              "as": "m",
              "in": {
                "$cond": [
                  {
                    "$gte": [
                      "$$m",
                      3
                    ]
                  },
                  "UPDATED!",
                  "$$m"
                ]
              }
            }
          }
        }
      }
    ])
    

    对于文档成员,您可以像下面这样操作,只需将 10 添加到 qty 字段。
    (如果 MongoDB 5 你可以使用$setField instead $mergeObjects

    Example2, members are documents

    db.collection.update({
      "_id": {
        "$eq": 1
      }
    },
    [
      {
        "$addFields": {
          "myarray": {
            "$map": {
              "input": "$myarray",
              "as": "d",
              "in": {
                "$mergeObjects": [
                  "$$d",
                  {
                    "qty": {
                      "$add": [
                        "$$d.qty",
                        10
                      ]
                    }
                  }
                ]
              }
            }
          }
        }
      }
    ])
    

    【讨论】:

      猜你喜欢
      • 2021-09-23
      • 2020-01-03
      • 2015-09-21
      • 2014-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多