如何基于起止日期与指定星期几从MongoDB返回多条记录
如何基于给定起止日期与MongoDB文档指定的星期几,返回符合条件的多条记录?
输入参数
- 查询起止日期:
start = "2022-09-08" end = "2022-09-17"
- MongoDB原始文档:
{ "id": "63199ee82baa3643e58ed0f1", "start": "2022-09-08", "end": "2022-09-20", "startTime": "09:00", "endTime": "05:10", "timezone": "Europe/Rome", "days": [ "Friday" ], "type": { "type": "remote", "label": "Video" }, "interval": "15m", "store": "63199ee82baa3643e5887676" }
需求说明
需要返回查询起止日期范围内属于星期五的日期(2022-09-09和2022-09-16)对应的记录,每条记录的start和end字段替换为对应日期,其余字段与原文档一致。
解决方案:使用MongoDB聚合管道实现
通过聚合管道的多阶段处理,可以精准生成符合要求的多条记录,具体步骤如下:
- 匹配目标原始文档:先筛选出自身时间范围与查询范围有重叠的文档,避免无效处理。
- 生成查询区间内的所有日期:根据输入的起止日期,生成该区间内的每一天日期序列。
- 筛选符合指定星期的日期:将生成的日期转换为星期名称,匹配文档
days数组指定的星期几。 - 替换日期字段并保留其他内容:把筛选后的日期作为新的
start和end值,复制原文档其他字段,生成最终记录。
具体聚合查询代码
db.collection.aggregate([ // 匹配原始文档,确保文档时间范围与查询范围有交集 { $match: { $expr: { $and: [ { $lte: ["$start", new Date("2022-09-17")] }, { $gte: ["$end", new Date("2022-09-08")] } ] } } }, // 生成查询范围内的所有日期(结束日期+1天确保包含最后一天) { $addFields: { dateRange: { $map: { input: { $range: [ { $toLong: { $dateFromString: { dateString: "2022-09-08" } } }, { $toLong: { $dateFromString: { dateString: "2022-09-18" } } }, 24 * 60 * 60 * 1000 // 每天的毫秒数 ] }, as: "timestamp", in: { $toDate: "$$timestamp" } } } } }, // 展开日期数组,逐个处理每个日期 { $unwind: "$dateRange" }, // 筛选出符合指定星期几的日期(将星期名称转为MongoDB对应的数值) { $match: { $expr: { $in: [ { $dayOfWeek: { date: "$dateRange", timezone: "$timezone" } }, { $map: { input: "$days", as: "day", in: { $add: [{ $indexOfArray: [["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], "$$day"] }, 1] } } } ] } } }, // 替换start和end为当前日期,保留其他字段 { $project: { id: 1, start: { $dateToString: { format: "%Y-%m-%d", date: "$dateRange", timezone: "$timezone" } }, end: { $dateToString: { format: "%Y-%m-%d", date: "$dateRange", timezone: "$timezone" } }, startTime: 1, endTime: 1, timezone: 1, days: 1, type: 1, interval: 1, store: 1 } }, // 按日期排序,结果更规整 { $sort: { start: 1 } } ])
执行结果
运行上述聚合查询后,将得到预期输出:
[ { "id": "63199ee82baa3643e58ed0f1", "start": "2022-09-09", "end": "2022-09-09", "startTime": "09:00", "endTime": "05:10", "timezone": "Europe/Rome", "days": [ "Friday" ], "type": { "type": "remote", "label": "Video" }, "interval": "15m", "store": "63199ee82baa3643e5887676" }, { "id": "63199ee82baa3643e58ed0f1", "start": "2022-09-16", "end": "2022-09-16", "startTime": "09:00", "endTime": "05:10", "timezone": "Europe/Rome", "days": [ "Friday" ], "type": { "type": "remote", "label": "Video" }, "interval": "15m", "store": "63199ee82baa3643e5887676" } ]
内容的提问来源于stack exchange,提问作者Akash Vishwakarma
相关产品推荐
相关产品推荐

