如何用Mongoose获取指定站点最近7天的detections数据?
MongoDB筛选嵌套数组中最近7天数据的方案
前提说明
你的示例中datetime字段只有时间(如"05:00 pm"),没有日期信息,这样根本没法筛选「最近7天」的数据。请务必确保datetime存储为完整的日期时间格式——推荐用MongoDB原生的ISODate类型,或者带日期的标准字符串(如"2024-05-20 17:00:00"),以下所有方案默认datetime是可用于日期比较的合法格式。
方案一:使用Aggregate管道(最灵活)
用聚合管道可以精准控制数组过滤逻辑,步骤清晰:
- 先匹配目标站点,缩小处理范围
- 重新生成
detections数组,只保留符合时间条件的元素
代码示例:
// 计算7天前的时间戳 const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); const siteResult = await SiteModel.aggregate([ // 第一步:定位目标站点 { $match: { _id: mongoose.Types.ObjectId(siteID) } }, // 第二步:过滤detections数组 { $addFields: { detections: { $filter: { input: "$detections", cond: { // 判断元素的datetime是否晚于7天前 $gte: ["$$this.datetime", sevenDaysAgo] } } } } } ]); // aggregate返回数组,取第一个元素即为目标站点 const targetSite = siteResult[0];
如果你的datetime是字符串格式,需要先转成Date类型再比较,将cond修改为:
cond: { $gte: [{ $toDate: "$$this.datetime" }, sevenDaysAgo] }
方案二:使用find投影(更简洁)
如果不需要复杂聚合操作,直接在find查询的投影里用$filter也能实现,代码更简短:
const sevenDaysAgo = new Date(); sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7); const targetSite = await SiteModel.findById(siteID, { // 保留你需要的其他字段 name: 1, timezone: 1, location: 1, // 过滤detections数组 detections: { $filter: { input: "$detections", cond: { $gte: ["$$this.datetime", sevenDaysAgo] } } } });
额外提示
- 若数据量较大,给
detections.datetime字段加索引能显著提升查询速度 - 测试时可以先打印
sevenDaysAgo的值,确认时间范围正确 - 字符串格式的datetime一定要转成Date类型再比较,否则会按字符串字典序排序,导致筛选结果错误
内容的提问来源于stack exchange,提问作者chomprrr
相关产品推荐
相关产品推荐

