You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB 4.4中如何生成到期日提前1/3个月的计算字段?

MongoDB 4.4 日期偏移查询优化方案(字符串日期场景)

需求明确

需要从集合中筛选满足以下任一条件的记录:

  • 字段expiryDate(YYYY-MM-DD字符串格式)等于当前日期
  • expiryDate等于当前日期加1个月(即当前日期是到期日提前1个月的提醒节点)
  • expiryDate等于当前日期加3个月(即当前日期是到期日提前3个月的提醒节点)

由于MongoDB 4.4不支持$dateAdd,且直接用毫秒计算月份会因每月天数不同产生误差,需要用日期拆分重组的方式实现精准的月份偏移。

优化后的聚合查询

db.getCollection('torjak_requests').aggregate([
    // 前置过滤:缩小处理范围,提升性能
    {
        $match: {
            expiryDateS: {
                $gte: { $dateToString: { format: "%Y-%m-%d", date: new Date() } },
                $lte: { $dateToString: { format: "%Y-%m-%d", date: new Date(new Date().setMonth(new Date().getMonth() + 3)) } }
            }
            // 可添加其他业务过滤条件
        }
    },
    // 合并日期转换与目标日期计算
    {
        $addFields: {
            // 字符串日期转ISO格式
            expiryDate: { $dateFromString: { dateString: "$expiryDateS" } },
            // 生成当前日期+1个月的目标字符串
            target1MonthLater: {
                $dateToString: {
                    format: "%Y-%m-%d",
                    date: {
                        $dateFromParts: {
                            year: { $year: new Date() },
                            month: { $add: [{ $month: new Date() }, 1] },
                            day: { $dayOfMonth: new Date() },
                            hour: 0,
                            minute: 0,
                            second: 0,
                            millisecond: 0
                        }
                    }
                }
            },
            // 生成当前日期+3个月的目标字符串
            target3MonthsLater: {
                $dateToString: {
                    format: "%Y-%m-%d",
                    date: {
                        $dateFromParts: {
                            year: { $year: new Date() },
                            month: { $add: [{ $month: new Date() }, 3] },
                            day: { $dayOfMonth: new Date() },
                            hour: 0,
                            minute: 0,
                            second: 0,
                            millisecond: 0
                        }
                    }
                }
            }
        }
    },
    // 匹配符合条件的记录
    {
        $match: {
            $or: [
                { expiryDateS: { $dateToString: { format: "%Y-%m-%d", date: new Date() } } },
                { expiryDateS: "$target1MonthLater" },
                { expiryDateS: "$target3MonthsLater" }
            ]
        }
    },
    // 清理临时字段
    {
        $project: {
            expiryDate: 0,
            target1MonthLater: 0,
            target3MonthsLater: 0
        }
    }
])

优化说明

  1. 前置过滤减少数据量:先通过$match筛选出日期范围在当前日到当前日+3个月内的记录,避免无意义的后续计算。
  2. 合并聚合阶段:将日期转换、目标日期计算合并到同一个$addFields阶段,减少阶段切换的开销。
  3. 精准日期偏移:用$dateFromParts拆分重组日期,直接实现月份加减,避免毫秒计算的天数误差。
  4. 统一日期精度:指定时分秒为0,确保与原字符串日期的精度一致,避免因时间部分差异导致匹配失败。

针对你现有方案的精简优化

如果需要基于记录的expiryDate生成提前日期字段,可以合并步骤减少冗余:

db.getCollection('torjak_requests').aggregate([
    { $match: { /* 业务过滤条件 */ } },
    {
        $addFields: {
            expiryDate: { $dateFromString: { dateString: "$expiryDateS" } },
            // 一次性生成两个提前日期的字符串
            expiryDate1MonthBeforeS: {
                $dateToString: {
                    format: "%Y-%m-%d",
                    date: {
                        $dateFromParts: {
                            year: { $year: "$expiryDate" },
                            month: { $add: [{ $month: "$expiryDate" }, -1] },
                            day: { $dayOfMonth: "$expiryDate" },
                            hour: 0, minute: 0, second: 0, millisecond: 0
                        }
                    }
                }
            },
            expiryDate3MonthsBeforeS: {
                $dateToString: {
                    format: "%Y-%m-%d",
                    date: {
                        $dateFromParts: {
                            year: { $year: "$expiryDate" },
                            month: { $add: [{ $month: "$expiryDate" }, -3] },
                            day: { $dayOfMonth: "$expiryDate" },
                            hour: 0, minute: 0, second: 0, millisecond: 0
                        }
                    }
                }
            }
        }
    },
    // 可添加匹配当前日期的逻辑:
    // { $match: { $or: [{ expiryDateS: currentStr }, { expiryDate1MonthBeforeS: currentStr }, { expiryDate3MonthsBeforeS: currentStr }] } },
    { $project: { expiryDate: 0 } }
])

内容的提问来源于stack exchange,提问作者Borgy Manotoy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 11:07:03