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

MongoDB聚合查询:筛选特定日期处于活跃状态的用户

MongoDB查询特定日期处于活跃状态的用户(基于start/end日期数组)

问题背景

用户集合中每个文档包含startDates(激活开始日期数组)和endDates(激活结束日期数组),规则如下:

  • 每个startDates[i]对应endDates[i],构成一个激活周期
  • 若startDates长度大于endDates,说明用户当前处于激活状态(最后一个开始日期无对应结束日期)
  • 需要查询指定日期(如12.05.2020、22.11.2022)处于活跃的用户,排除17.12.2021这类不符合的日期

示例文档:

{
  "active" : true,
  "endDates" : [
     "16.11.2021",
     "27.06.2020"
  ],
  "startDates" : [
    "21.10.2022",
    "16.10.2021",
    "09.04.2020"
  ]   
}

原方案问题

直接对两个数组执行两次$unwind会生成所有日期的笛卡尔积组合,无法对应真实的激活周期,导致筛选逻辑失效。

正确解决方案

核心思路是:先将字符串日期转为MongoDB标准Date类型,再按索引配对生成真实激活周期,最后判断目标日期是否落在任意周期内。

完整聚合代码:

// 替换为你要查询的目标日期,注意格式为YYYY-MM-DD
const targetDate = new Date("2020-05-12");

collection.aggregate([
  // 1. 将dd.mm.yyyy格式的字符串日期转为MongoDB Date类型
  {
    $addFields: {
      parsedStartDates: {
        $map: {
          input: "$startDates",
          in: {
            $dateFromString: {
              dateString: "$$this",
              format: "%d.%m.%Y"
            }
          }
        }
      },
      parsedEndDates: {
        $map: {
          input: "$endDates",
          in: {
            $dateFromString: {
              dateString: "$$this",
              format: "%d.%m.%Y"
            }
          }
        }
      }
    }
  },
  // 2. 按索引配对生成激活周期,处理"当前活跃"的情况(无结束日期)
  {
    $addFields: {
      activePeriods: {
        $map: {
          input: { $range: [0, { $size: "$parsedStartDates" }] },
          as: "index",
          in: {
            start: { $arrayElemAt: ["$parsedStartDates", "$$index"] },
            end: {
              $cond: {
                if: { $lt: ["$$index", { $size: "$parsedEndDates" }] },
                then: { $arrayElemAt: ["$parsedEndDates", "$$index"] },
                else: null // null代表当前持续激活,无结束日期
              }
            }
          }
        }
      }
    }
  },
  // 3. 判断目标日期是否落在任意激活周期内
  {
    $addFields: {
      isActiveOnTarget: {
        $anyElementTrue: {
          $map: {
            input: "$activePeriods",
            in: {
              $cond: {
                if: { $eq: ["$$this.end", null] },
                // 当前活跃:目标日期 >= 开始日期
                then: { $gte: [targetDate, "$$this.start"] },
                // 已结束周期:目标日期在[start, end]区间内
                else: { $and: [{ $gte: [targetDate, "$$this.start"] }, { $lte: [targetDate, "$$this.end"] }] }
              }
            }
          }
        }
      }
    }
  },
  // 4. 筛选出符合条件的用户
  { $match: { isActiveOnTarget: true } },
  // 可选:清理聚合过程中生成的临时字段,返回原文档结构
  { $project: { parsedStartDates: 0, parsedEndDates: 0, activePeriods: 0, isActiveOnTarget: 0 } }
])

逻辑验证

  • 针对2020-05-12:匹配周期2020-04-09至2020-06-27,符合条件
  • 针对2022-11-22:startDates长度大于endDates,最后一个开始日期为2022-10-21,目标日期晚于该日期,符合条件
  • 针对2021-12-17:所有已结束周期均不包含该日期,且最后一个开始日期2022-10-21晚于目标日期,不符合条件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:40:27