【问题标题】:MongoDB aggregation $group with mutually exclusive fields OR split / unwind documents具有互斥字段或拆分/展开文档的 MongoDB 聚合 $group
【发布时间】:2020-07-27 11:23:32
【问题描述】:

我有一个带有架构的集合,具有互斥字段:

{
  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 将始终同时出现。 AND它们之间有不同的值。

MongoPlayground example

有没有人有任何想法分裂这对双胞胎并取得这样的结果?像这样:

  {
    "_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
  }

附:我知道使用这个模式是完全失败的,但我没有计划它。所以我不能在我自己的图像中重新构建集合。

更新:我已经做了什么?

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

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

【问题讨论】:

  • 您可以只使用 JavaScript 更新现有文档然后为条件{ a_item_id: { $exists: true}, h_item_id: { $exists: true} } 为每个文档插入一个新文档 - 这要简单得多。
  • @prasad_。关键是:need to split documents via aggregate stage 它是巨大的聚合查询的一部分

标签: mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

此聚合使用另一种方法,使用$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
}

【讨论】:

    【解决方案2】:

    «好吧,我自己做»

    MongoPlayground example for future uses

    Model.aggregate([
      {
        $match: {
          $or: [
            {
              a_item_id: 2,
              
            },
            {
              h_item_id: 3,
              
            },
            {
              item_id: 1,
              
            }
          ]
        }
      },
      {
        $addFields: {
          item_id: {
            $filter: {
              input: [
                "$item_id",
                "$h_item_id",
                "$a_item_id"
              ],
              as: "d",
              cond: {
                $ne: [
                  "$$d",
                  null
                ]
              }
            }
          }
        }
      },
      {
        $unset: [
          "a_item_id",
          "h_item_id",
          
        ]
      },
      {
        $unwind: {
          path: "$item_id",
          preserveNullAndEmptyArrays: true
        }
      },
      {
        $group: {
          _id: "$item_id"
        }
      }
    ])
    
    

    最后一组我可以添加:

      data: {
        $push: "$$ROOT"
      }
    

    然后$unwind数据域接收原始文件。

    【讨论】:

    • 只是一些想法。使用$facet 阶段也可以拆分文档。此外,您可以使用$$REMOVE 取消设置字段。
    • @prasad_谢谢你的建议,我以前在 MongoDB 文档中看到过$facet。我也考虑使用$project 舞台,而不是$addFields$unset 舞台。
    猜你喜欢
    • 2020-11-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 2023-02-11
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多