MongoDB/Mongoose如何判断给定日期时分是否在timings数组时间范围内
实现方案
分两种常用实现路径,可根据业务场景选择:
方案1:应用层判断(逻辑简单,易调试修改)
适合请求量小、后续需要对时间判断逻辑做自定义扩展的场景
- 第一步:将输入的ISO日期转换为可直接比较的数值
const inputDate = new Date(输入的ISO日期字符串); const inputWeekday = inputDate.getDay(); // JS默认返回0=周日,1=周一,6=周六 const inputTotalMinutes = inputDate.getHours() * 60 + inputDate.getMinutes();
- 第二步:查询文档后遍历判断
// 先查询目标从业者文档 const targetPractitioner = await Practitioner.findOne({ // 补充你的查询条件,例如 _id: 从业者ID }); if (!targetPractitioner) return false; // 校验当前日期是否属于排班的周末范围 const isWeekendScheduled = targetPractitioner.schedules.weekend.includes(inputWeekday); if (!isWeekendScheduled) return false; // 校验是否落在任意时间区间内 const isInRange = targetPractitioner.schedules.timings.some(timing => { const fromTotal = timing.from.hour * 60 + timing.from.minute; const toTotal = timing.to.hour * 60 + timing.to.minute; return inputTotalMinutes >= fromTotal && inputTotalMinutes <= toTotal; }); return isInRange;
方案2:MongoDB聚合查询(数据库侧直接返回结果,性能更高)
适合高并发场景,无需拉取全量文档到应用层,减少数据传输开销
const inputDate = new Date(输入的ISO日期字符串); const inputWeekday = inputDate.getDay(); const inputTotalMinutes = inputDate.getHours() * 60 + inputDate.getMinutes(); const aggregateResult = await Practitioner.aggregate([ // 第一步:过滤目标从业者+匹配周末排班规则,减少后续计算量 { $match: { // 补充你的查询条件,例如 _id: 从业者ID "schedules.weekend": inputWeekday }}, // 第二步:直接在数据库侧计算时间匹配结果 { $addFields: { isMatch: { $anyElementTrue: { $map: { input: "$schedules.timings", as: "t", in: { $and: [ { $gte: [ inputTotalMinutes, { $add: [ { $multiply: ["$$t.from.hour", 60] }, "$$t.from.minute" ] } ]}, { $lte: [ inputTotalMinutes, { $add: [ { $multiply: ["$$t.to.hour", 60] }, "$$t.to.minute" ] } ]} ] } } } } }}, // 第三步:仅返回需要的布尔值 { $project: { isMatch: 1, _id: 0 } } ]); // 无匹配文档返回false,有匹配返回对应计算结果 const finalResult = aggregateResult.length ? aggregateResult[0].isMatch : false;
注意:如果你的
schedules.weekend存储的星期数值规则和JSgetDay()默认规则不一致,请提前调整inputWeekday的数值和存储规则对齐,避免匹配错误。
内容的提问来源于stack exchange,提问作者Raffi
相关产品推荐
相关产品推荐

