MongoDB单查询获取调查活跃与总用户数方案咨询
MongoDB 单查询同时统计调查活跃用户数与总用户数
需求
将两个独立查询合并为单个MongoDB聚合查询,同时返回指定调查的活跃用户数(提交有效响应的去重用户)和总用户数(参与调查的所有去重用户,含活跃/非活跃)。
集合结构示例
Survey 集合
{ "_id": ObjectId("60d21b4667d0d8992e610c85"), "surveyId": "survey_001", "title": "用户满意度调查", "createdAt": ISODate("2021-06-23T10:00:00Z") }
survey_response 集合
{ "_id": ObjectId("60d21b8967d0d8992e610c86"), "surveyId": "survey_001", "userId": "user_123", "isValid": true, // 标记响应是否有效 "submittedAt": ISODate("2021-06-23T10:30:00Z") }
期望返回结果
{ "totalUsers": 100, "activeUsers": 75 }
当前实现(两个独立查询)
统计总用户数
db.survey_response.aggregate([ { $match: { surveyId: "survey_001" } }, { $group: { _id: "$userId" } }, { $count: "totalUsers" } ])
统计活跃用户数
db.survey_response.aggregate([ { $match: { surveyId: "survey_001", isValid: true } }, { $group: { _id: "$userId" } }, { $count: "activeUsers" } ])
优化后的单查询实现
db.survey_response.aggregate([ // 过滤目标调查的所有响应记录 { $match: { surveyId: "survey_001" } }, // 按用户分组,标记该用户是否存在有效响应 { $group: { _id: "$userId", hasValidResponse: { $max: "$isValid" } // 只要用户有一条有效响应,就标记为活跃 } }, // 聚合统计总用户数和活跃用户数 { $group: { _id: null, totalUsers: { $sum: 1 }, activeUsers: { $sum: { $cond: [{ $eq: ["$hasValidResponse", true] }, 1, 0] } } } }, // 整理输出格式,移除冗余字段 { $project: { _id: 0, totalUsers: 1, activeUsers: 1 } } ])
逻辑说明
$match:筛选出指定调查的所有响应数据,减少后续处理量- 第一层
$group:按用户ID去重,用$max判断该用户是否有有效响应(只要有一条isValid: true就标记为活跃) - 第二层
$group:聚合所有用户分组,统计总用户数(每组算1个),通过$cond条件累加活跃用户数 $project:调整输出结构,移除不需要的_id字段
进阶优化(关联Survey集合)
如果需要先验证调查存在,可关联Survey集合查询:
db.survey.aggregate([ { $match: { surveyId: "survey_001" } }, { $lookup: { from: "survey_response", localField: "surveyId", foreignField: "surveyId", as: "responses" } }, { $unwind: { path: "$responses", preserveNullAndEmptyArrays: true } }, { $group: { _id: "$responses.userId", hasValidResponse: { $max: { $ifNull: ["$responses.isValid", false] } } } }, { $group: { _id: null, totalUsers: { $sum: { $cond: [{ $ne: ["$_id", null] }, 1, 0] } }, activeUsers: { $sum: { $cond: [{ $eq: ["$hasValidResponse", true] }, 1, 0] } } } }, { $project: { _id: 0, totalUsers: 1, activeUsers: 1 } } ])
内容的提问来源于stack exchange,提问作者Anilkumar Kalyane
相关产品推荐
相关产品推荐

