MongoDB时间戳转日期及按日期聚合统计的技术咨询
嘿,针对你提到的MongoDB聚合操作的三个问题,我结合你的示例数据(你给的示例里只有_id是时间戳字符串,我默认你说的creation_time是类似格式的时间戳字段哈),给你一步步梳理解法:
1. 将MongoDB中的时间戳转换为日期
因为你的时间戳是字符串格式(比如示例里的"1522845653126"),得先把它转成数值型时间戳,再转换成标准日期格式。MongoDB提供了$toLong和$toDate两个操作符来实现:
db.collection.aggregate([ { $addFields: { // 先转数值时间戳,再转ISODate creation_date: { $toDate: { $toLong: "$creation_time" } } } } ])
小提示:如果你的creation_time本身就是数值类型(比如1522845653126而非字符串),可以简化成creation_date: { $toDate: "$creation_time" }
2. 统计特定日期的条目数量
这里有两种常用思路,按需选择:
方法一:直接匹配特定日期并计数
先把时间戳转成日期,再筛选出目标日期范围内的文档,最后统计总数:
db.collection.aggregate([ { $addFields: { creation_date: { $toDate: { $toLong: "$creation_time" } } } }, { $match: { // 匹配2018-04-04全天的文档(UTC时间) creation_date: { $gte: ISODate("2018-04-04T00:00:00Z"), $lt: ISODate("2018-04-05T00:00:00Z") } } }, { $count: "total_entries" // 输出结果为 { "total_entries": N } } ])
方法二:先按日期分组统计所有日期,再筛选特定日期
如果需要同时查看多个日期的统计结果,先按天分组,再按需筛选:
db.collection.aggregate([ { $addFields: { creation_date: { $toDate: { $toLong: "$creation_time" } } } }, { $group: { // 按YYYY-MM-DD格式的日期字符串分组 _id: { $dateToString: { format: "%Y-%m-%d", date: "$creation_date" } }, count: { $sum: 1 } // 统计每组的条目数 } }, // 可选:筛选出特定日期的结果 { $match: { _id: "2018-04-04" } } ])
3. 处理5天数据,将同一天的结果与次日结果聚合
这个需求是要把当天的条目数和次日的条目数合并统计,针对连续5天的数据,会生成4组“当天+次日”的结果(比如第1+2天、2+3天、3+4天、4+5天)。我们可以用MongoDB的窗口函数来实现,步骤如下:
db.collection.aggregate([ // 步骤1:转换时间戳为日期,并按天分组统计每日条目数 { $addFields: { creation_date: { $toDate: { $toLong: "$creation_time" } } } }, { $group: { _id: { $dateTrunc: { date: "$creation_date", unit: "day" } }, // 按天截断日期,确保分组准确 daily_count: { $sum: 1 } } }, // 步骤2:按日期升序排序,保证窗口函数能正确获取次日数据 { $sort: { _id: 1 } }, // 步骤3:用窗口函数`$shift`获取次日的条目数 { $setWindowFields: { partitionBy: null, // 全局窗口,所有文档在同一分区 sortBy: { _id: 1 }, output: { next_day_count: { $shift: { output: "$daily_count", by: 1, default: 0 } } // 取下一个文档的计数,默认0(最后一天没有次日) } } }, // 步骤4:计算当天+次日的总条目数,并格式化日期字符串方便查看 { $addFields: { combined_count: { $add: ["$daily_count", "$next_day_count"] }, date_str: { $dateToString: { format: "%Y-%m-%d", date: "$_id" } }, next_day_str: { $dateToString: { format: "%Y-%m-%d", date: { $add: ["$_id", 86400000] } } } // 加一天的毫秒数(24*60*60*1000) } }, // 步骤5:筛选出5天范围内的数据(这里假设处理2018-04-01到2018-04-05的日期) { $match: { _id: { $gte: ISODate("2018-04-01T00:00:00Z"), $lt: ISODate("2018-04-05T00:00:00Z") // 保留前4天,和次日合并后覆盖5天 } } }, // 步骤6:整理输出字段,让结果更直观 { $project: { _id: 0, date_range: { $concat: ["$date_str", " - ", "$next_day_str"] }, combined_count: 1 } } ])
执行后会得到类似这样的结果:
{ "date_range" : "2018-04-01 - 2018-04-02", "combined_count" : 5 } { "date_range" : "2018-04-02 - 2018-04-03", "combined_count" : 3 } ...
内容的提问来源于stack exchange,提问作者user8934737
相关产品推荐
相关产品推荐

