【问题标题】:How to optimise aggregation query to group based on different keys?如何优化聚合查询以根据不同的键进行分组?
【发布时间】:2020-11-06 05:00:14
【问题描述】:

我的 mongoDB 文档如下所示:

[
  {
    "fields": {
      "field_1": {
        "name": "f1",
        "first": {
          "check": true
        }
      },
      "field_2": {
        "name": "f2",
        "second": {
          "check": true
        }
      },
      "field_3": {},
      "field_4": {
        "name": "f4",
        "second": {
          "check": true
        }
      }
    }
  },
  {
    "fields": {
      "field_1": {
        "name": "f1",
        "second": {
          "check": false
        }
      },
      "field_2": {
        "name": "f2",
        "second": {
          "check": true
        },
        "first": {
          "check": true
        }
      },
      "field_3": {
        "name": "f3",
        "second": {
          "check": true
        }
      }
    }
  }
]

预期输出:

  1. 创建父组 f1(fields.field1.name) 和 f2(fields.field2.name)

  2. 他们每个人都有两个子组,这些子组根据以下条件显示指标 各自的父组:

    1. first_group:first.check=true 的文档计数
    2. second_group:first.check 不存在且 second.check=true 的文档计数

结果:

[
  {
    "data": [
      {
        "_id": "f1",
        "values": [
          {     
            "second_group": 0,
            "first_group": 1
          }
        ]
      },
      {
        "_id": "f2",
        "values": [
          {
            "second_group": 1,
            "first_group": 1
          }
        ]
      }
    ]
  }
]

我已经使用 $facet 生成了查询,但我不满意,因为我必须在每个父组中重复我的子级分组逻辑(我在 $facet 中有 4 个数组)

My Query in Mongo Playground attached here

请告诉我如何删除重复查询。 有没有其他方法可以实现这个用例?

谢谢!

【问题讨论】:

  • 基础预期 O/p 并查看条件使之成为 play query。看看这是否有帮助以及你在寻找什么。
  • 虽然我需要 $facet 进行一些并行操作(我的实际用例更复杂),但这正是我想要的!非常感谢@ambianBeing
  • 将其作为答案发布。考虑接受它。很高兴这有效。

标签: mongodb mongodb-query aggregation-framework grouping aggregation


【解决方案1】:

发布应该适用于给定条件和预期 O/p 的聚合查询:

db.collection.aggregate([
  {
    $unwind: "$fields",
  },
  {
    $project: {
      data: {
        $objectToArray: "$fields",
      },
    },
  },
  {
    $unwind: "$data",
  },
  {
    $match: {
      "data.v.first.check": true,
    },
  },
  {
    $group: {
      _id: "$data.v.name",
      values: {
        $push: {
          first_group: {
            $sum: {
              $cond: [
                {
                  $eq: ["$data.v.first.check", true],
                },
                1,
                0,
              ],
            },
          },
          second_group: {
            $sum: {
              $cond: [
                {
                  $eq: ["$data.v.second.check", true],
                },
                1,
                0,
              ],
            },
          },
        },
      },
    },
  },
]);

Play link

【讨论】:

    【解决方案2】:

    替代解决方案:

    我们将fields 属性标准化,并使用$convert 运算符将first_groupsecond_group 值计算为Integer,并使用此behavior

    Input Type  Behavior
    ---------------------
    Boolean     Returns 0 for false.
                Returns 1 for true.
    

    db.collection.aggregate([
      {
        $project: {
          fields: {
            $map: {
              input: [
                "$fields.field_1",
                "$fields.field_2"
              ],
              as: "field",
              in: {
                _id: "$$field.name",
                first_group: {
                  $convert: {
                    input: "$$field.first.check",
                    to: 16,
                    onNull: 0
                  }
                },
                second_group: {
                  $convert: {
                    input: {
                      $and: [
                        {
                          $eq: [
                            {
                              $type: "$$field.first.check"
                            },
                            "missing"
                          ]
                        },
                        "$$field.second.check"
                      ]
                    },
                    to: 16,
                    onNull: 0
                  }
                }
              }
            }
          }
        }
      },
      {
        $unwind: "$fields"
      },
      {
        $group: {
          _id: "$fields._id",
          first_group: {
            $sum: "$fields.first_group"
          },
          second_group: {
            $sum: "$fields.second_group"
          }
        }
      },
      {
        $group: {
          _id: null,
          data: {
            $push: {
              _id: "$_id",
              values: [
                {
                  first_group: "$first_group",
                  second_group: "$second_group"
                }
              ]
            }
          }
        }
      }
    ])
    

    MongoPlayground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      • 1970-01-01
      • 2010-12-18
      • 2016-10-04
      • 2021-09-03
      • 2010-10-23
      • 1970-01-01
      相关资源
      最近更新 更多