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

MongoDB聚合$match中$and匹配多日期$eq表达式返回空数组问题

问题解决:MongoDB匹配两个月份的销售数据

核心错误分析

你的查询返回空数组,主要存在两个关键问题:

  1. 逻辑运算符误用:使用$and要求单条文档的createdAt同时匹配两个不同月份的年月,这显然不可能——单条文档只能属于一个月份,应该用$or替代$and。
  2. 日期变量计算错误:Date是可变类型,setMonth会直接修改原date对象,导致lastMonth和prevMonth的实际值与预期不符。

修复步骤

1. 修正日期变量的计算

避免修改原date对象,通过创建新Date实例生成目标月份(建议设为当月第一天,规避日期溢出问题,比如3月31日减1月会自动转为3月3日):

const date = new Date();
// 上个月(例:当前是2023年2月,则为2023年1月1日)
const lastMonth = new Date(date.getFullYear(), date.getMonth() - 1, 1);
// 上上个月(例:当前是2023年2月,则为2022年12月1日)
const prevMonth = new Date(date.getFullYear(), date.getMonth() - 2, 1);

2. 修正$match阶段的逻辑

将$and替换为$or,匹配属于prevMonth年月 或 lastMonth年月的文档:

{
  $match: {
    $expr: {
      $or: [
        {
          $eq: [
            { $dateFromParts: { month: { $month: '$createdAt' }, year: { $year: '$createdAt' } } },
            { $dateFromParts: { month: { $month: prevMonth }, year: { $year: prevMonth } } }
          ]
        },
        {
          $eq: [
            { $dateFromParts: { month: { $month: '$createdAt' }, year: { $year: '$createdAt' } } },
            { $dateFromParts: { month: { $month: lastMonth }, year: { $year: lastMonth } } }
          ]
        }
      ]
    }
  }
}

可选优化:更高效的匹配方式

如果createdAt字段有索引,推荐用范围查询替代$expr,利用索引提升查询效率:

// 计算每个月份的起始/结束日期
const prevMonthStart = new Date(prevMonth.getFullYear(), prevMonth.getMonth(), 1);
const prevMonthEnd = new Date(prevMonth.getFullYear(), prevMonth.getMonth() + 1, 1);
const lastMonthStart = new Date(lastMonth.getFullYear(), lastMonth.getMonth(), 1);
const lastMonthEnd = new Date(lastMonth.getFullYear(), lastMonth.getMonth() + 1, 1);

// 匹配目标月份范围内的文档
{
  $match: {
    createdAt: {
      $or: [
        { $gte: prevMonthStart, $lt: prevMonthEnd },
        { $gte: lastMonthStart, $lt: lastMonthEnd }
      ]
    }
  }
}

内容的提问来源于stack exchange,提问作者Tai Abrahams

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:10:19