首页 > 解决方案 > 具有互斥字段或拆分/展开文档的 MongoDB 聚合 $group

问题描述

我有一个带有模式的集合,具有互斥字段:

{
  item_id: Number, //if this field is present in document
  a_item_id: Number, //then this both field doesn't exists and vice versa
  h_item_id: Number, //then this both field doesn't exists and vice versa
  quantity: Number,
  other_field: String
}

问题:

我需要aggregate按这样的顺序通过阶段拆分文档,每个包含a_item_id&& h_item_id(双)字段的文档都将成为两个单独的文档(它们应该继承它们的基本字段)

另外,重点是,我不能同时$group通过两个字段,然后$unwind因为,如果这些字段出现在文档中,它们之间总是具有不同的值,例如:

a_item_id: 2
h_item_id: 3

因此,如果item_id不在文档中,则a_item_idh_item_id总是同时出现。并且它们彼此之间具有不同的值。

MongoPlayground示例

有谁知道分裂这对双胞胎并取得这样的结果?像这样:

  {
    "_id": ObjectId("5a934e000102030405000000"),
    "item_id": 1,
    "quantity": 1
  },
  {
    "_id": ObjectId("5a934e000102030405000001"),
    "a_item_id": 2,
    "quantity": 1
  },
  {
    "_id": ObjectId("5a934e000102030405000002"),
    "h_item_id": 3,
    "quantity": 1
  }

PS 我知道使用这个模式是完全失败的,但我没有计划它。所以我不能以我自己的形象重建收藏。

更新:我已经做了什么?

我正在尝试通过添加新数组并将每个文档中的每个值推送到它来解决我的问题,以备后用$unwind

  {
    $addFields: {
      items_array: [
        "$item_id",
        "$h_item_id",
        "$a_item_id"
      ]
    }
  }

标签: mongodbmongoosemongodb-queryaggregation-framework

解决方案


此聚合使用另一种方法,使用$facet阶段:

db.collection.aggregate([
  { 
      $match: { a_item_id: { $exists: true },  h_item_id: { $exists: true } } 
  },
  { 
      $facet: {
          doc_a_item: [ 
               { $addFields: { h_item_id: "$$REMOVE" } },
          ],
          doc_h_item: [
               { $addFields: { a_item_id: "$$REMOVE" } }
          ]
       } 
  },
  { 
      $project: { doc: { $concatArrays: [ "$doc_a_item", "$doc_h_item" ] } } 
  },
  { 
      $unwind: "$doc" 
  },
  { 
      $replaceWith: "$doc" 
  }
] )

输出,作为两个文档:

{
        "_id" : ObjectId("5f1ed8090fdddd9a43c261e5"),
        "a_item_id" : 34,
        "quantity" : 50
}
{
        "_id" : ObjectId("5f1ed8090fdddd9a43c261e5"),
        "h_item_id" : 56,
        "quantity" : 50
}

输入文件

{
    _id : ObjectId("5f1ed8090fdddd9a43c261e5"), 
    a_item_id: 34, 
    h_item_id: 56, 
    quantity: 50
}

推荐阅读