MongoDB按性别、婚姻状况、职业类别分组统计用户实现方法
MongoDB users集合多维度统计聚合实现方案
核心实现思路
单$group阶段无法同时对多个独立字段做分组计数,$unwind方案会产生不必要的笛卡尔积、性能差,最优方案是使用$facet聚合阶段,在单次表扫描的前提下并行执行多个独立统计分支,同时完成全局指标和多维度分布的计算。
完整聚合语句
db.getCollection("users").aggregate([ { $facet: { // 全局指标:总用户数、已验证用户数 baseStats: [ { $group: { _id: null, total: { $sum: 1 }, validated: { $sum: { $cond: [{ $eq: ["$state", "VALIDATED"] }, 1, 0] } } } } ], // 性别分布统计 genders: [ { $group: { _id: "$gender", count: { $sum: 1 } } }, { $project: { _id: 0, value: "$_id", count: 1 } } ], // 婚姻状况分布统计 civilStatus: [ { $group: { _id: "$civilStatus", count: { $sum: 1 } } }, { $project: { _id: 0, value: "$_id", count: 1 } } ], // 职业类别分布统计 professionalCategories: [ { $group: { _id: "$professionalCategory", count: { $sum: 1 } } }, { $project: { _id: 0, value: "$_id", count: 1 } } ] } }, // 合并各分支结果为目标结构 { $replaceRoot: { newRoot: { $mergeObjects: [ { $arrayElemAt: ["$baseStats", 0] }, { genders: "$genders" }, { civilStatus: "$civilStatus" }, { professionalCategories: "$professionalCategories" } ] } } } ])
逻辑说明
$facet下的4个分支会并行执行,互不干扰:baseStats分支复用已有的验证用户计数逻辑,补充$sum:1计算总用户数- 三个维度分布分支各自按对应字段分组计数,通过
$project将分组键_id重命名为value,输出符合要求的{value, count}结构
- 最后通过
$replaceRoot+$mergeObjects把facet返回的分块结果合并成单层平面对象,完全匹配期望的返回格式。
可选优化
如果不需要统计字段为空/不存在的异常数据,可以在每个维度分支的$group前增加$match阶段过滤无效值,以性别统计为例:
genders: [ { $match: { gender: { $exists: true, $ne: null } } }, { $group: { _id: "$gender", count: { $sum: 1 } } }, { $project: { _id: 0, value: "$_id", count: 1 } } ]
内容的提问来源于stack exchange,提问作者user18991485
相关产品推荐
相关产品推荐

