MongoDB 3.6聚合分组后合并低计数类别为Others的实现方案
MongoDB 3.6 实现保留前2高计数类别、合并其余为Others的聚合方案
针对你的需求,我们可以在现有聚合逻辑的基础上,通过$facet、$concatArrays等操作来实现动态合并剩余类别为Others的效果。下面是完整的可直接运行的聚合查询,以及分步解释:
完整聚合查询
db.cmi5DashboardData.aggregate([ // 1. 基础分组统计:按Category求和response,排序并投影格式 { $group: { _id: '$Category', knt: { $sum: '$response' } } }, { $sort: { knt: -1 } }, { $project: { _id: 0, category: '$_id', count: '$knt' } }, // 2. 用$facet并行处理两个分支:取前2个类别、剩余类别求和 { $facet: { topCategories: [ { $limit: 2 } ], // 获取排序后的前2个高计数类别 otherCategories: [ { $skip: 2 }, // 跳过前2个类别 { $group: { _id: 'Others', count: { $sum: '$count' } } } // 对剩余类别的count求和 ] } }, // 3. 合并两个分支的结果数组 { $project: { combined: { $concatArrays: [ '$topCategories', '$otherCategories' ] } } }, // 4. 展开合并后的数组为单个文档 { $unwind: '$combined' }, // 5. 将每个文档的内容提升为根文档,得到最终格式 { $replaceRoot: { newRoot: '$combined' } } ])
分步解释
- 基础统计阶段:这部分就是你原本的聚合逻辑,完成按
Category分组求和response,按计数降序排序,最后投影成category和count的清晰格式。 - $facet并行处理:MongoDB 3.6支持的
$facet可以在一个聚合中同时运行多个独立的子管道:topCategories子管道用$limit:2直接获取排序后的前2个高计数类别(也就是你的例子中的Privacy和Mobile)。otherCategories子管道先用$skip:2跳过前2个类别,再用$group把剩下所有类别的count累加,统一命名为Others。
- 合并与格式化:通过
$concatArrays把两个子管道的结果数组合并,再用$unwind拆分成单个文档,最后用$replaceRoot把文档结构调整成你需要的{Category, count}格式。
边界情况说明
- 如果总类别数小于2个(比如只有1个类别),
otherCategories子管道会返回空数组,最终结果只会显示存在的类别,不会出现Others。 - 如果需要在类别数不足2时仍显示
Others(count为0),可以在otherCategories中添加$ifNull或$cond处理,比如在$group后加$project设置默认值,不过一般按业务需求选择即可。
内容的提问来源于stack exchange,提问作者N Raghu
相关产品推荐
相关产品推荐

