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

如何用Mongoose查询指定日期区间与MongoDB数组日期是否重叠

修复MongoDB日期重叠查询问题

原查询的核心问题是逻辑错误,只匹配了「现有预订时间段完全包含指定时间段」的场景,漏掉了其他所有重叠情况;另外还有不必要的日期格式转换可能导致类型不匹配。

日期重叠的正确判断逻辑

两个时间段存在重叠的反面是「完全不重叠」,完全不重叠的条件只有两种:

  • 现有预订的结束日期 ≤ 指定的起始日期
  • 现有预订的起始日期 ≥ 指定的结束日期

所以我们只需要查询不满足上述任一条件的文档,就能找到存在重叠预订的记录。

修复后的Mongoose查询代码

// 确保initDate和endingDayBufferCalcWithContractDays是Date类型,无需转成字符串
const getAvailabilityDetails = await Products.find({
  _id: pid,
  bookings: {
    $elemMatch: {
      $nor: [
        { productBookingCompleteDate: { $lte: initDate } },
        { productBookingStartDate: { $gte: endingDayBufferCalcWithContractDays } }
      ]
    }
  }
});

等价的$or写法(枚举所有重叠场景)

如果更直观的话,也可以直接枚举所有重叠的情况:

const getAvailabilityDetails = await Products.find({
  _id: pid,
  bookings: {
    $elemMatch: {
      $or: [
        // 现有预订包含指定时间段
        { productBookingStartDate: { $lte: initDate }, productBookingCompleteDate: { $gte: endingDayBufferCalcWithContractDays } },
        // 指定时间段包含现有预订
        { productBookingStartDate: { $gte: initDate }, productBookingCompleteDate: { $lte: endingDayBufferCalcWithContractDays } },
        // 现有预订开始于指定时间段内
        { productBookingStartDate: { $gte: initDate, $lte: endingDayBufferCalcWithContractDays } },
        // 现有预订结束于指定时间段内
        { productBookingCompleteDate: { $gte: initDate, $lte: endingDayBufferCalcWithContractDays } }
      ]
    }
  }
});

关键注意事项

  • 确保initDate和endingDayBufferCalcWithContractDays是Date对象,不要转成ISO字符串或其他格式,MongoDB会自动处理Date类型的比较
  • 使用$elemMatch确保数组中至少有一个booking满足重叠条件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:45:16