MongoDB聚合查询:筛选近6个月的DD-MM-YYYY格式日期数据
问题排查与修复
你的聚合查询返回空数组,核心存在两个问题:
1. 时间比较的类型不匹配
now.setMonth()返回的是Unix时间戳(数字),而$dateFromString转换后得到的是MongoDB的Date对象。虽然MongoDB支持跨类型比较,但这种写法易引发隐性逻辑错误。
2. 日期计算的副作用
setMonth()会直接修改原now对象,属于不良编码习惯,可能导致后续日期逻辑混乱。
修复后的代码
const now = new Date(); // 新建独立Date对象,避免修改原now的引用 const sixMonthsAgo = new Date(now); sixMonthsAgo.setMonth(now.getMonth() - 6); const data = await MyModel.aggregate([ // 前置过滤:仅保留存在有效日期字符串的文档,减少无效计算 { $match: { "admin.emailSentDate": { $exists: true, $type: "string" } } }, { $addFields: { // 新建解析后的日期字段,不覆盖原始字符串 "admin.emailSentDateParsed": { $dateFromString: { dateString: "$admin.emailSentDate", format: "%d-%m-%Y", // 格式错误时返回null,方便后续过滤无效数据 onError: null } } } }, // 过滤出解析成功且日期在近6个月内的记录 { $match: { "admin.emailSentDateParsed": { $gte: sixMonthsAgo, $ne: null } } }, // 可选:如果不需要解析后的字段,可移除该步骤 { $project: { "admin.emailSentDateParsed": 0 } } ]);
额外说明
- 前置
$match筛选有效文档,能大幅减少后续日期解析的运算量。 - 使用
onError: null处理格式错误的日期字符串,避免聚合报错,同时排除无效数据。 - 保留原始字符串字段,避免覆盖后丢失原始信息,也减少潜在的业务冲突。
内容的提问来源于stack exchange,提问作者SosijElizabeth
相关产品推荐
相关产品推荐

