将字段替换为 MongoDB 聚合。为什么 $set、$addFields 和 $project 并不总是替换字段?

Replace field with MongoDB aggregate. Why $set, $addFields and $project, doesn't always replace the field?

将对象传递到 $set$addFields 中的现有字段 合并 个对象而不是替换它们,例如

https://mongoplayground.net/p/aXe-rExjCXr

// Collection
[
  {
    "_id": "123",
    "options": {
      "size": "Large",
      "color": "Red"
    }
  }
]
// Aggregate
db.collection.aggregate([
  {
    $set: {
      options: {
        size: "Small"
      }
    }
  }
]);
// Expect
[
  {
    "_id": "123",
    "options": {
      "size": "Small"
    }
  }
]
// Actual
[
  {
    "_id": "123",
    "options": {
      "size": "Small",
      "color": "Red" // <-- Not expected?
    }
  }
]

(数组更奇怪)

是否可以让它表现得像非对象值并简单地替换该字段?

对于上下文,我想在 aggregate update pipeline.

中使用它

这是预期的行为,据我所知没有改变的计划,据我记得有一个 jira,但他们关闭了它,这意味着我认为它不会改变。

$set/$addFields 始终替换

  • array 字段,我添加 document => 包含 document
  • 的所有成员的数组
  • 文档字段和我添加文档=>合并文档(这是你的情况)

$project 始终替换

  • array 字段,我添加 document => 包含 document
  • 的所有成员的数组

解决方案

  • 您可以覆盖这种“奇怪”的行为,尤其是在 数组,例如先 $unset 旧字段,然后 $set
  • 根据下面评论中的jira,我们也可以使用$literal来避免这种情况,但是当我们使用$literal时,我们必须确保我们不使用表达式,因为它们不会进行评估。 (路径引用、变量、运算符等表达式)