Mongoose查询需求:获取近24小时内每小时一条气象传感器数据
嘿,这个需求用MongoDB的聚合框架就能完美解决!单纯的find查询没法直接实现按小时分组并只保留单条记录的逻辑,咱们用聚合管道来一步步实现:
核心思路
通过聚合的几个阶段组合,先筛选出近24小时的数据,再按小时分组,每组只保留一条记录(比如该小时的第一条或最后一条数据),最后按时间排序方便绘图。
具体实现代码
const last24HoursData = await Measurements.aggregate([ // 1. 筛选近24小时的所有测量数据 { $match: { createdAt: { $gt: new Date(Date.now() - 24 * 60 * 60 * 1000) } } }, // 2. 按小时分组,每组取该小时的最后一条记录(也可以换成$first取第一条) { $group: { _id: { // 把时间截断到小时级别,MongoDB 5.0+支持$dateTrunc $dateTrunc: { date: "$createdAt", unit: "hour" } }, temperature: { $last: "$temperature" }, humidity: { $last: "$humidity" }, // 保留该条记录的具体创建时间 recordTime: { $last: "$createdAt" } } }, // 3. 按小时顺序排序,让结果从最早到最晚排列 { $sort: { "_id": 1 } }, // 4. 可选:重命名字段让结果更易读 { $project: { _id: 0, hourStart: "$_id", // 该小时的起始时间(比如2024-05-20 18:00:00) temperature: 1, humidity: 1, recordTime: 1 } } ]);
针对旧版本MongoDB的兼容方案
如果你的MongoDB版本低于5.0(不支持$dateTrunc),可以用$dateToString来生成小时级别的字符串作为分组键:
// 在$group的_id里替换成这个 _id: { $dateToString: { format: "%Y-%m-%d %H:00:00", date: "$createdAt" } }
小提示
- 如果你想取每小时的第一条数据,只需要把所有的
$last换成$first就行。 - 因为你的传感器每5分钟发一次数据,每个小时都会有12条记录,所以每个分组都会有数据返回,不会出现空小时的情况(如果需要处理空小时的场景,还需要额外的逻辑,但你的需求里应该不用)。
内容的提问来源于stack exchange,提问作者Aleksander Sadaj
相关产品推荐
相关产品推荐

