Mongodb 使用合并对象而不覆盖子文档

Mongodb 使用合并对象而不覆盖子文档,mongodb,Mongodb,我正在尝试合并聚合管道中的两个字段 我想改变这一点: { "a": 1, "b": { "first": { "property_a": "some_value", "property_b": "some_value", "property_c": "some_value" }, "second": { "property_a": "some_value",

我正在尝试合并聚合管道中的两个字段

我想改变这一点:

{
   "a": 1,
   "b": {
      "first": {
          "property_a": "some_value",
          "property_b": "some_value",
          "property_c": "some_value"
      },
      "second": {
          "property_a": "some_value",
          "property_b": "some_value",
          "property_c": "some_value"
      },
      "third": {
          "property_a": "some_value",
          "property_b": "some_value",
          "property_c": "some_value"
      },
      "fiftieth": {
          "property_a": "some_value",
          "property_b": "some_value",
          "property_c": "some_value"
      }
   },
   "c": {
      "first": {
          "property_x": "some_value",
          "property_y": "some_value"
      },
      "second": {
          "property_x": "some_value",
          "property_y": "some_value"
      },
      "fiftieth": {
          "property_x": "some_value",
          "property_y": "some_value"
      }
   }
}
在这种情况下,无需指定“b”下列出的每个键:

mergeObjects
的文档中,它指出:

合并对象在合并文档时覆盖字段值。如果要合并的文档包含相同的字段名,则结果文档中的字段具有上次合并文档中的值


如何在不指定每个键的情况下合并字段b和c的子文档(在我的实际用例中有85个键)。此外,字段c可能没有在b下列出所有键。或者这是不可能的

您可以使用
$objectToArray
将对象转换为k、v对,组合并
$unwind
它们,
$group
按键名并合并文档,然后
$group
按_-id将键收集回一起

db.collection.aggregate([
  {$addFields: {
      combined: {
        $concatArrays: [
          {$objectToArray: "$b"},
          {$objectToArray: "$c"}
        ]
      }
  }},
  {$unwind: "$combined"},
  {$group: {
      _id: {_id: "$_id", key: "$combined.k"},
      doc: {$first: "$$ROOT"},
      v: {$mergeObjects: "$combined.v"}
  }},
  {$group: {
      _id: "$_id._id",
      doc: {$first: "$doc"},
      combined: {$push: {
          k: "$_id.key",
          v: "$v"
      }}
  }},
  {$addFields: {"doc.b": {$arrayToObject: "$combined"}}},
  {$project: {
    combined: 0,
    "doc.c": 0
  }},
  {$replaceRoot: {newRoot: "$doc"}}
])

是否确定
b
c
中的任何字段都不会包含文档以外的内容?是的。字段b和c仅包含文档。此解决方案有效。我真的很感谢你的帮助!非常感谢你!
db.collection.aggregate([
  {$addFields: {
      combined: {
        $concatArrays: [
          {$objectToArray: "$b"},
          {$objectToArray: "$c"}
        ]
      }
  }},
  {$unwind: "$combined"},
  {$group: {
      _id: {_id: "$_id", key: "$combined.k"},
      doc: {$first: "$$ROOT"},
      v: {$mergeObjects: "$combined.v"}
  }},
  {$group: {
      _id: "$_id._id",
      doc: {$first: "$doc"},
      combined: {$push: {
          k: "$_id.key",
          v: "$v"
      }}
  }},
  {$addFields: {"doc.b": {$arrayToObject: "$combined"}}},
  {$project: {
    combined: 0,
    "doc.c": 0
  }},
  {$replaceRoot: {newRoot: "$doc"}}
])