MongoDB如何按15分钟时间间隔分组统计各时段在线用户
可以仅使用MongoDB原生聚合能力实现该需求,不需要引入自定义JavaScript脚本,核心思路是先计算每个用户连接时段覆盖的所有15分钟时间槽,再展开后分组统计。
完整聚合语句
collection.aggregate([ // 1. 计算每个会话的起始时间槽、结束时间槽 { $addFields: { slotStep: 1000 * 60 * 15, // 15分钟对应的毫秒数 startSlot: { $toDate: { $subtract: [ { $toLong: "$connection" }, { $mod: [{ $toLong: "$connection" }, 1000 * 60 * 15] } ] } }, endSlot: { $toDate: { $subtract: [ { $toLong: "$disconnection" }, { $mod: [{ $toLong: "$disconnection" }, 1000 * 60 * 15] } ] } } } }, // 2. 生成该会话覆盖的所有时间槽数组 { $addFields: { // 计算覆盖的槽位总数,+1是因为首尾槽都需要计入 slotCount: { $add: [ { $divide: [ { $subtract: ["$endSlot", "$startSlot"] }, "$slotStep" ] }, 1 ] } } }, { $addFields: { timeSlots: { $map: { // 生成从0到slotCount-1的偏移序列 input: { $range: [0, "$slotCount"] }, as: "offset", in: { $add: ["$startSlot", { $multiply: ["$$offset", "$slotStep"] }] } } } } }, // 3. 把每个时间槽拆成独立文档 { $unwind: "$timeSlots" }, // 4. 按时间槽分组统计 { $group: { _id: "$timeSlots", count: { $sum: 1 }, users: { $addToSet: "$user" } } }, // 按时间正序排序 { $sort: { _id: 1 } } ])
关键逻辑说明
- 槽位对齐计算:对每个会话的连接、断开时间都做15分钟向下取整,得到该会话覆盖的第一个和最后一个时间槽
- 多槽位生成:通过
$range生成偏移序列,批量转换为所有覆盖的时间槽,解决跨时段统计问题 - 展开后分组:
$unwind将每个时间槽拆分为独立文档后,再按时间槽分组即可得到每个时段的所有在线用户
内容的提问来源于stack exchange,提问作者Laubuur
相关产品推荐
相关产品推荐

