从分组的 mongo 聚合中的对象数组创建对象

问题描述 投票:0回答:1

我一直在编写一个聚合管道来显示集合中数据的汇总版本。

文档结构示例:

{
    _id: 'abcxyz',
    eventCode: 'EVENTCODE01',
    eventName: 'SOMEEVENT',
    units: 1,
    rate: 2,
    cost: 2,
    distribution: [
        {
            startDate: 2021-05-31T04:00:00.000+00:00
            units: 1
        }
    ]
}

我已将其分组,并将分布合并到一个列表中,并在

$unwind
之前执行
$group
步骤:

[
    $unwind: {
        path: '$distribution',
        preserveNullAndEmptyArrays: false
    },
    $group: {
        _id: {
            eventName: '$eventName',
            eventCode: '$eventCode'
        },
        totalUnits: {
            $sum: '$units'
        },
        distributionList: {
            $push: '$distribution'
        },
        perUnitRate: {
            $avg: '$rate'
        },
        perUnitCost: {
            $avg: '$cost'
        }
    }
]

示例输出:

{
    _id: {
        eventName: 'EVENTNAME101'
        eventCode: 'QQQ'
    },
    totalUnits: 7,
    perUnitRate: 2,
    perUnitCost: 2,
    distributionList: [
        {
            startDate: 2021-05-31T04:00:00.000+00:00,
            units: 1
        },
        {
            startDate: 2021-05-31T04:00:00.000+00:00,
            units: 1
        },
        {
            startDate: 2021-06-07T04:00:00.000+00:00,
            units: 1
        }
    ]
}

我陷入下一步;我想将

distributionList
合并到一个新列表中,不重复
startDate

示例:由于 distributionList 的前 2 个对象具有相同的 startDate,因此它应该是输出中具有单位总和的单个对象:

预期:

{
    _id: {
        eventName: 'EVENTNAME101'
        eventCode: 'QQQ'
    },
    totalUnits: 7,
    perUnitRate: 2,
    perUnitCost: 2,
    newDistributionList: [
        {
            startDate: 2021-05-31T04:00:00.000+00:00,
            units: 2 //units summed for first 2 objects
        },
        {
            startDate: 2021-06-07T04:00:00.000+00:00,
            units: 1
        }
    ]
}

我无法使用

$unwind
$bucket
,因为我打算保留在之前步骤中所做的分组 (
$group
)。

如果这看起来不准确,我可以获得建议或不同的方法吗?

mongodb mongodb-query aggregation-framework nosql-aggregation
1个回答
1
投票

您可能想要在

$group
级别执行第一个
eventName, eventCode, distribution.startDate
。然后,您可以在
$group
级别再次
eventName, eventCode
并使用
$first
保留原始
$group
字段。

db.collection.aggregate([
  {
    $unwind: {
      path: "$distribution",
      preserveNullAndEmptyArrays: false
    }
  },
  {
    $group: {
      _id: {
        eventName: "$eventName",
        eventCode: "$eventCode",
        distributionStartDate: "$distribution.startDate"
      },
      totalUnits: {
        $sum: "$units"
      },
      distributionUnitsSum: {
        $sum: "$distribution.units"
      },
      perUnitRate: {
        $avg: "$rate"
      },
      perUnitCost: {
        $avg: "$cost"
      }
    }
  },
  {
    $group: {
      _id: {
        eventName: "$_id.eventName",
        eventCode: "$_id.eventCode"
      },
      totalUnits: {
        $first: "$totalUnits"
      },
      newDistributionList: {
        $push: {
          startDate: "$_id.distributionStartDate",
          units: "$distributionUnitsSum"
        }
      },
      perUnitRate: {
        $first: "$perUnitRate"
      },
      perUnitCost: {
        $first: "$perUnitCost"
      }
    }
  }
])

这里是 Mongo Playground 展示这个想法供大家参考。

© www.soinside.com 2019 - 2024. All rights reserved.