MongoDB Update Aggregation Pipeline 能否有条件地替换文档?

Can MongoDB Update Aggregation Pipeline conditionally replace the document?

给定一个文档;

{
  "name": "Jason",
  "foo": "bar",
  "version": 3,
  // ...
}

是否可以指定更新聚合管道以根据当前文档的 属性 有条件地更新整个文档?即指定类似;

const newDocument = { ...currentDocument, version: 4, foo: "baz" };

if (document.version == 3) 
  $replaceRoot(newDocument)
else
  doNothing()

Post 回答编辑

下面标记的答案确实解决了这个问题。为了完整起见,我想添加一些背景来说明为什么会问这个问题,因为答案会略有变化。

CosmosDB 提供 Optimistic Concurrency Control (OCC) 的功能,允许 CosmosDB 在文档发生意外更改时拒绝文档上的命令。需要注意的重要一点是,客户端可以提供文档的预期版本 (_etag 属性)。

MongoDB 确实在后台使用了此功能,但不会向客户端公开 OCC。这意味着您的整个文档更改需要在 Mongo 更新管道语法中进行描述。这种语法适用于简单的文档和更新命令。但是,它不能替代可测试的业务逻辑代码。

要在使用 MongoDB 时向客户端公开 OCC,请使用 version 属性 或类似的并确保在命令过滤器中以预期版本为目标,如所述 .

是的,可以,您可以像以前一样在代码中构建更新管道,但您也可以在 Mongo 中使用 $cond 这样做:

db.collection.updateOne({},
[
  {
    $replaceRoot: {
      newRoot: {
        $cond: [
          {
            $eq: [
              "$version",
              3
            ]
          },
          {
            $mergeObjects: [
              "$$ROOT",
              {
                version: 4,
                foo: "baz"
              }
            ]
          },
          "$$ROOT"
        ]
      }
    }
  }
])

Mongo Playground