如何改写MongoDB聚合管道?实现按角色统计用户总数量与活跃数量
MongoDB 按角色与活跃状态生成指定格式的聚合统计
我需要根据用户的role(角色)和isActive(活跃状态)生成聚合统计结果,期望输出格式如下:
{ "role": { "user": { "all": 3, "active": 2 }, "admin": { "all": 1, "active": 1 }, "vendor": { "all": 2, "active": 2 } } }
当前使用的聚合查询及返回结果无法满足格式要求,以下是相关信息:
示例文档
{ "email": "doe@gmail.com", "firstName": "doe", "lastName": "bghh", "phone": "+919016703350", "password":"$.5GIV3q9JqzRqY/lP2", "status": "verified", "role": "admin", "isActive": true }
当前聚合查询
const user = await User.aggregate([ { $project: { isActive: 1, role: 1 } }, { $group: { _id: { role: '$role', isActive: '$isActive' }, all: { $sum: 1 } } }, ])
当前查询结果
{ "user": [ { "_id": { "role": "user", "isActive": false }, "all": 1 }, { "_id": { "role": "vendor", "isActive": true }, "all": 1 }, { "_id": { "role": "user", "isActive": true }, "all": 2 }, { "_id": { "role": "vendor", "isActive": false }, "all": 1 }, { "_id": { "role": "admin", "isActive": true }, "all": 1 } ] }
解决方案:调整后的聚合查询语句
const userStats = await User.aggregate([ // 筛选需要的字段,减少数据处理量 { $project: { role: 1, isActive: 1 } }, // 按角色分组,统计总数量和活跃用户数 { $group: { _id: "$role", all: { $sum: 1 }, active: { $sum: { $cond: [{ $eq: ["$isActive", true] }, 1, 0] } } } }, // 将分组结果整理为键值对数组 { $group: { _id: null, roles: { $push: { k: "$_id", v: { all: "$all", active: "$active" } } } } }, // 转换为目标格式并替换根文档 { $replaceRoot: { newRoot: { role: { $arrayToObject: "$roles" } } } } ])
语句说明
- $project:仅保留
role和isActive字段,避免不必要的数据处理。 - 第一个$group:按角色分组,用
$sum统计该角色的总用户数;用$cond判断用户是否活跃,累加得到活跃用户数。 - 第二个$group:把所有角色的统计结果收集成包含键值对的数组,为后续转换对象做准备。
- $replaceRoot:通过
$arrayToObject将数组转为键值对对象,最终包装成{ role: {...} }的目标格式。
内容的提问来源于stack exchange,提问作者sunilsalat
相关产品推荐
相关产品推荐

