MongoDB查询:如何筛选日期时间为字符串格式的今日记录
解决方案
由于你的日期和时间是分开存储的字符串类型,直接用普通find查询的比较逻辑无法生效,需要通过字符串转日期对象的方式来实现筛选,以下是两种可行方案:
方法一:聚合管道组合日期时间并筛选
该方案先锁定今日记录,再将拆分的日期时间字段组合成完整的日期对象,最终筛选出早于当前时间的记录:
const now = new Date(); // 生成和match_date格式一致的今日字符串(如"17-Sep") const todayMatchDate = `${now.getDate()}-${now.toLocaleString('en-US', { month: 'short' })}`; db.posts.aggregate([ // 第一步:筛选今日的记录 { $match: { match_date: todayMatchDate } }, // 第二步:将match_date和match_time组合为完整的Date对象 { $addFields: { full_match_datetime: { $dateFromString: { dateString: `${now.getFullYear()} ${match_date.replace('-', ' ')} ${match_time}`, format: "%Y %d %b %I:%M %p" } } } }, // 第三步:筛选出早于当前时间的记录 { $match: { full_match_datetime: { $lt: now } } }, // 可选:移除临时生成的full_match_datetime字段 { $project: { full_match_datetime: 0 } } ])
代码说明
todayMatchDate:生成与match_date格式完全匹配的今日字符串,避免处理非今日的历史记录。$dateFromString:将拼接后的日期时间字符串(如"2023 17 Sep 01:30 PM")转换为MongoDB可识别的Date对象,格式符对应规则:%Y=年份,%d=日期,%b=英文月份缩写,%I=12小时制小时,%M=分钟,%p=AM/PM标识。
方法二:使用$expr在find中直接比较(简化版)
如果不想用聚合管道,可通过$expr在find中编写表达式,直接完成转换与比较:
const now = new Date(); const todayMatchDate = `${now.getDate()}-${now.toLocaleString('en-US', { month: 'short' })}`; db.posts.find({ match_date: todayMatchDate, $expr: { $lt: [ { $dateFromString: { dateString: `${now.getFullYear()} ${match_date.replace('-', ' ')} ${match_time}`, format: "%Y %d %b %I:%M %p" } }, now ] } })
注意事项
- 确保你的MongoDB版本在3.6及以上(
$dateFromString从该版本开始支持)。 - 数据中的月份缩写必须是英文格式(如
Sep),如果是其他语言缩写,需要调整toLocaleString参数和format格式符。 - 若需处理跨年场景,需注意年份取值的准确性,但你的需求是筛选今日记录,使用当前年份即可。
长期优化建议
如果后续有大量时间筛选需求,建议修改文档结构,将match_date和match_time合并为一个Date类型的字段(如match_datetime),这样查询无需每次做字符串转换,效率会大幅提升,后续只需用db.posts.find({match_datetime: {$lt: new Date()}})即可完成筛选。
内容的提问来源于stack exchange,提问作者Piyush
相关产品推荐
相关产品推荐

