如何用MongoDB聚合查询计算每日新增唯一会话占比?
当然可以用MongoDB的聚合框架实现这个需求!我们需要拆解问题,一步步处理数据来得到你想要的结果。首先先明确核心逻辑:我们需要统计每日首次登录的唯一用户数,再计算这个数字占截至当日的累计总唯一用户数的百分比(或者根据你对“总会话”的定义调整分母)。
解决方案聚合管道
下面是针对你的模型和数据设计的聚合代码,我会逐步骤解释作用:
AnalyticsModel.aggregate([ // 1. 展开每个日期的登录记录数组,让每条用户登录单独成为一个文档 { $unwind: "$loginTrack" }, // 2. 只保留我们需要的字段,简化后续处理 { $project: { createdAt: 1, user_id: "$loginTrack.user_id" }}, // 3. 按用户ID分组,找到每个用户的首次登录日期 { $group: { _id: "$user_id", firstLoginDate: { $min: "$createdAt" } }}, // 4. 按首次登录日期分组,统计每日新增的唯一用户数 { $group: { _id: "$firstLoginDate", newUsers: { $sum: 1 } }}, // 5. 按日期升序排序,确保累计计算的顺序正确 { $sort: { _id: 1 } }, // 6. 使用窗口函数计算截至当日的累计总唯一用户数 { $setWindowFields: { sortBy: { _id: 1 }, output: { totalUniqueUsers: { $sum: "$newUsers", window: { documents: ["unbounded", "current"] } } } }}, // 7. 计算百分比并格式化输出字段 { $project: { _id: 0, date: "$_id", newSessionsAvg: { $round: [{ $multiply: [{ $divide: ["$newUsers", "$totalUniqueUsers"] }, 100] }, 2] } }} ])
步骤解释
- $unwind:把每个日期对应的
loginTrack数组拆分成独立文档,这样我们能单独处理每个用户的登录记录。 - $project:只保留日期和用户ID,过滤掉不需要的字段,减少后续计算的冗余。
- $group(按user_id):找到每个用户第一次登录的日期,这一步是区分“新增用户”和“回头用户”的核心。
- $group(按首次登录日期):统计每天有多少用户是首次登录,得到当日的新增唯一用户数。
- $sort:按日期升序排列,确保窗口函数能正确计算从第一天到当前日期的累计值。
- $setWindowFields:用窗口函数计算累计总唯一用户数,
["unbounded", "current"]表示统计范围从第一个文档到当前文档。 - $project:计算新增用户占累计用户的百分比(乘以100转为百分比格式,用
$round保留两位小数),并把字段名改成你需要的date和newSessionsAvg。
针对你的示例数据的输出
代入你提供的样本数据,运行后会得到:
[ {"date": "2018-03-22", "newSessionsAvg": 100}, {"date": "2018-03-23", "newSessionsAvg": 33.33}, {"date": "2018-03-24", "newSessionsAvg": 0} ]
如果你的“总会话”定义是累计登录会话次数(而非唯一用户数),可以调整聚合逻辑中的分母计算,把累计唯一用户数换成累计登录次数即可。
内容的提问来源于stack exchange,提问作者TLR
相关产品推荐
相关产品推荐

