MongoDB查最近7天数据需用$gte配合绝对时间戳,字段必须为Date类型且建索引;_id可按时间查询但精度仅秒;时区须统一为UTC,避免字符串或数字存时间。

直接用 $gte 配合当前时间减去7天的时间戳
MongoDB 本身没有“最近7天”这种相对时间语法,必须转成绝对时间点(ISODate 或 Unix 时间戳)再查。最常用、最可靠的方式是构造一个 $gte 查询,配合 new Date() 计算边界。
- Shell 中直接执行:
db.collection.find({ "createdAt": { "$gte": new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) } }) - 如果字段名不是
createdAt,而是timestamp、insertedAt或_id(ObjectId 自带时间),请替换成实际字段名 -
_id字段可间接用于时间查询——因为 ObjectId 的前4字节是时间戳,可用$gt比较:db.collection.find({ "_id": { "$gt": ObjectId(Math.floor(Date.now()/1000).toString(16) + "0000000000000000") } })但这种方式精度只到秒,且不推荐用于业务逻辑主时间判断
确保字段类型是 Date,不是字符串或数字
常见错误是把时间存成了字符串(如 "2025-06-15T10:20:30Z")或毫秒数(如 1718437230000)。MongoDB 的 $gte 对字符串做字典序比较,对数字做数值比较,结果都不可靠。
- 正确存法(Shell 示例):
db.collection.insertOne({ "createdAt": new Date(), "name": "test" }) - 验证字段类型:
db.collection.findOne().createdAt
返回类似ISODate("2025-06-15T10:20:30.123Z")才对 - 如果已存为字符串,不能直接用
$gte查时间范围;要么重建索引+转换数据,要么用$expr+$dateFromString(仅 MongoDB 4.0+,性能差,慎用)
加索引避免全表扫描
没索引时,createdAt 字段查询会触发 collection scan,数据量一过万就明显变慢。
- 建单字段索引:
db.collection.createIndex({ "createdAt": 1 }) - 如果常按用户 + 时间联合查(如
{ userId: 123, createdAt: { $gte: ... } }),建复合索引更高效:db.collection.createIndex({ "userId": 1, "createdAt": 1 }) - 注意:索引字段顺序很重要,等值查询字段(如
userId)必须放在范围查询字段(如createdAt)前面
PyMongo 或其他驱动里别忘了时区处理
Python 的 datetime.now() 默认是本地时区,而 MongoDB 存储的是 UTC 时间。如果应用服务器和数据库时区不一致,直接用本地时间计算会导致漏查或误查。
- 安全做法是统一用 UTC:
from datetime import datetime, timedelta seven_days_ago = datetime.utcnow() - timedelta(days=7) collection.find({ "createdAt": { "$gte": seven_days_ago } }) - Node.js 同理,用
new Date(Date.now() - 7*24*60*60*1000)是安全的(Date.now()返回 UTC 毫秒数) - 如果字段存的是带时区的字符串(如
"2025-06-15T10:20:30+08:00"),解析和比较逻辑会更复杂,应尽量避免
真正容易被忽略的是字段类型和时区一致性——很多线上问题不是语法写错,而是时间字段存错了类型,或者开发环境用本地时间测试、生产环境跑在 UTC 服务器上,结果查不到数据还反复检查查询语句。


















