如何通过MongoDB聚合查询直接按月份分组统计各公司交易数?
问题:MongoDB聚合查询直接转换为按月份分组的公司交易统计格式
需求说明
希望直接通过MongoDB聚合查询,按月份统计各公司的交易数量并输出目标格式,不用后续循环处理结果。
现有数据格式
[{ "id": "1", "month": "October", "company": "tesla", "saleId": "111" }, { "id": "2", "month": "October", "company": "ford", "saleId": "222" }, { "id": "3", "month": "October", "company": "tesla", "saleId": "333" }, { "id": "4", "month": "November", "company": "tesla", "saleId": "444" }, { "id": "5", "month": "December", "company": "kia", "saleId": "555" }, { "id": "6", "month": "December", "company": "ford", "saleId": "666" }]
期望输出格式
{ "October": [{ "company": "tesla", "count": 2 }, { "company": "ford", "count": 1 } ], "November": [{ "company": "tesla", "count": 1 }], "December": [{ "company": "kia", "count": 1 }, { "company": "ford", "count": 1 } ] }
当前聚合查询及结果
当前查询代码
let result = await con.aggregate([ { $group : { _id:{ month: "$month", company: "$company", }, count:{$sum:1} } } ]).toArray();
当前查询结果
[ { "_id": { "month": "October", "company": "tesla" }, "count": 2 }, { "_id": { "month": "November", "company": "tesla" }, "count": 1 }, { "_id": { "month": "October", "company": "ford" }, "count": 1 }, { "_id": { "month": "December", "company": "ford" }, "count": 1 }, { "_id": { "month": "December", "company": "kia" }, "count": 1 } ]
解决方案:扩展聚合管道完成格式转换
可以通过添加额外的聚合阶段,直接在查询层面得到目标格式,无需后续处理。修改后的聚合管道如下:
let result = await con.aggregate([ // 第一步:按月份+公司分组统计交易数量 { $group : { _id:{ month: "$month", company: "$company", }, count: {$sum: 1} } }, // 第二步:按月份重新分组,把同月份的公司统计结果整理为数组 { $group: { _id: "$_id.month", companyStats: { $push: { company: "$_id.company", count: "$count" } } } }, // 第三步:将文档转为键值对形式,月份作为键,统计数组作为值 { $replaceRoot: { newRoot: { $arrayToObject: [[{ k: "$_id", v: "$companyStats" }]] } } }, // 第四步:将所有月份的统计结果合并为单个对象(可选,需要单个对象而非数组时用) { $group: { _id: null, merged: { $mergeObjects: "$$ROOT" } } }, { $replaceRoot: { newRoot: "$merged" } } ]).toArray();
各阶段作用说明
- 第一阶段:和原查询逻辑一致,先按月份+公司的组合分组,统计每组的交易次数。
- 第二阶段:以月份为分组键,把每个月份下的公司统计数据(包含公司名和数量)收集到一个数组里。
- 第三阶段:用
$arrayToObject把当前文档转换成「月份: 统计数组」的键值对结构,再替换根文档。 - 第四阶段:如果需要最终结果是单个对象而不是多个对象的数组,就通过
$group和$mergeObjects把所有月份的统计结果合并成一个对象,最后替换根文档得到目标格式。
执行这个查询后,就能直接得到你想要的输出格式,不用再做后续循环处理。
内容的提问来源于stack exchange,提问作者Dev1ce
相关产品推荐
相关产品推荐

