使用MongoDB聚合自动计算各月活跃用户数(无需手动指定月份)
MongoDB聚合计算各月活跃独立用户数
聚合管道实现方案
以下聚合管道无需额外代码,完全通过MongoDB原生聚合操作实现自动化计算从第一个用户创建月到当前月的活跃用户数:
db.users.aggregate([ // 阶段1:获取全局时间边界(最早创建时间、当前时间)并保留所有用户数据 { $group: { _id: null, minCreatedAt: { $min: "$createdAt" }, currentDate: { $first: new Date() }, users: { $push: { _id: "$_id", createdAt: "$createdAt", deletedAt: "$deletedAt" } } } }, // 阶段2:计算月份总数,转换最早创建时间为当月第一天 { $addFields: { monthCount: { $ceil: { $divide: [ { $subtract: ["$currentDate", "$minCreatedAt"] }, 1000 * 60 * 60 * 24 * 30 // 近似月毫秒数,MongoDB会自动处理月份边界差异 ] } }, firstMonthStart: { $dateFromParts: { year: { $year: "$minCreatedAt" }, month: { $month: "$minCreatedAt" }, day: 1 } } } }, // 阶段3:生成从第一个月到当前月的完整月份序列 { $addFields: { months: { $map: { input: { $range: [0, "$monthCount", 1] }, as: "index", in: { $dateAdd: { startDate: "$firstMonthStart", unit: "month", amount: "$$index" } } } } } }, // 阶段4:展开用户列表,处理单个用户的活跃时间范围 { $unwind: "$users" }, { $addFields: { userEndDate: { $ifNull: ["$users.deletedAt", "$currentDate"] }, userStartMonth: { $dateFromParts: { year: { $year: "$users.createdAt" }, month: { $month: "$users.createdAt" }, day: 1 } }, userEndMonth: { $dateFromParts: { year: { $year: "$userEndDate" }, month: { $month: "$userEndDate" }, day: 1 } } } }, // 阶段5:过滤出该用户覆盖的所有活跃月份 { $addFields: { activeMonths: { $filter: { input: "$months", as: "month", cond: { $and: [ { $gte: ["$$month", "$userStartMonth"] }, { $lte: ["$$month", "$userEndMonth"] } ] } } } } }, // 阶段6:展开活跃月份,按月份分组收集唯一用户ID { $unwind: "$activeMonths" }, { $group: { _id: "$activeMonths", uniqueUsers: { $addToSet: "$users._id" } } }, // 阶段7:格式化月份为YYYY-MM格式,统计去重后的用户数 { $project: { _id: 0, month: { $dateToString: { format: "%Y-%m", date: "$_id" } }, count: { $size: "$uniqueUsers" } } }, // 阶段8:按月份升序排序 { $sort: { month: 1 } } ])
方案说明
- 全局时间边界获取:通过
$group聚合获取最早用户创建时间与当前时间,同时保留所有用户的核心数据。 - 自动化月份生成:计算时间跨度内的总月数,用
$range和$dateAdd生成连续月份序列,完全无需手动指定月份。 - 用户活跃范围匹配:为每个用户确定活跃起始/结束月份,过滤出该用户覆盖的所有目标月份。
- 独立用户统计:使用
$addToSet收集每个月的唯一用户ID,再通过$size计算去重后的用户数量,确保统计结果为独立用户数。
示例验证
针对你提供的3条用户测试数据,执行上述管道后将输出与预期完全一致的结果,每个月份的活跃用户数精准匹配用户的创建/删除时间范围。
内容的提问来源于stack exchange,提问作者Float07
相关产品推荐
相关产品推荐

