MongoDB聚合查询需求:实现缺失月份计数补0的分组统计
MongoDB聚合查询:补全缺失月份的计数为0
以下是能够实现需求的完整聚合查询方案:
let result = await con.aggregate([ // 过滤有效数据(保留原匹配条件) { $match : { year : "2023", "deliveryPartner.name": { $ne: null }, "country": { $ne: null }, "month": { $ne: null } } }, // 按配送商、国家、月份分组统计数量 { $group: { _id: { deliveryPartner: "$deliveryPartner.name", country: "$country", month: "$month" }, count: { $sum: 1 } } }, // 按配送商+国家聚合,整理已有月份的计数数据 { $group: { _id: { deliveryPartner: "$_id.deliveryPartner", country: "$_id.country" }, existingMonths: { $push: { k: "$_id.month", v: "$count" } } } }, // 定义需要覆盖的全量月份列表(可根据实际需求扩展) { $addFields: { allMonths: [ "Jan", "Feb" ] } }, // 遍历全量月份,补全缺失月份的计数为0 { $addFields: { monthData: { $map: { input: "$allMonths", as: "month", in: { $arrayToObject: [[{ k: "$$month", v: { $cond: [ { $in: [ "$$month", "$existingMonths.k" ] }, { $arrayElemAt: [ "$existingMonths.v", { $indexOfArray: [ "$existingMonths.k", "$$month" ] } ] }, 0 ] } }]] } } } } }, // 格式化输出结构,去除冗余字段 { $project: { _id: 0, deliveryPartner: "$_id.deliveryPartner", country: "$_id.country", month: "$monthData" } } ]).toArray(); console.log("result => ", JSON.stringify(result));
核心逻辑说明
- 初始分组统计:先统计每个(配送商+国家+月份)组合的实际订单数,保留原有的过滤和第一次分组逻辑。
- 聚合已有数据:将同一配送商+国家下的月份数据整理为键值对数组,方便后续匹配。
- 定义全量月份:明确需要覆盖的所有月份(示例为Jan、Feb,若需全年可扩展为12个月份)。
- 补全缺失数据:通过
$map遍历全量月份,用$cond判断当前月份是否有统计数据,存在则取实际值,不存在则设为0,再通过$arrayToObject转换为目标格式的对象。 - 输出格式化:调整字段名称,去除不必要的
_id字段,输出符合要求的结构。
原查询的问题
原查询仅会聚合存在实际数据的月份,无法自动补全缺失月份的0值。必须先定义全量月份集合,再通过匹配补全的方式实现需求。
内容的提问来源于stack exchange,提问作者Dev1ce
相关产品推荐
相关产品推荐

