如何在MongoDB中基于day和month字段查询明日过生日的用户
查询明日过生日的MongoDB用户方案
当然可以通过处理birthDay和birthMonth字段来筛选明日过生日的用户,甚至不用完全生成DateTime字段也能实现高效查询,以下是两种可行方案:
方案一:直接匹配月日(推荐,性能更优)
不需要生成额外DateTime字段,直接通过表达式匹配明日的月份和日期,同时处理跨年边界情况(比如12月31日的次日是1月1日):
// 获取明日的日期信息 const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); const tomorrowMonth = tomorrow.getMonth() + 1; // MongoDB月份为1-12,JS原生是0-11,需加1 const tomorrowDay = tomorrow.getDate(); // 构建查询条件 db.users.find({ $expr: { $or: [ // 普通情况:月日完全匹配 { $and: [ { $eq: ["$aboutPage.birthMonth", tomorrowMonth] }, { $eq: ["$aboutPage.birthDay", tomorrowDay] } ] }, // 跨年情况:今日是12月31日,明日是1月1日 { $and: [ { $eq: ["$aboutPage.birthMonth", 1] }, { $eq: ["$aboutPage.birthDay", 1] }, { $eq: [tomorrowMonth, 1] }, { $eq: [tomorrowDay, 1] } ] } ] } });
方案二:生成DateTime字段后筛选
如果一定要生成DateTime字段,可以用聚合管道先构造生日日期(基于当前年份),再和明日日期对比,同样需要处理跨年场景:
const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); // 格式化明日为yyyy-MM-dd字符串,忽略时间部分 const tomorrowStr = `${tomorrow.getFullYear()}-${String(tomorrow.getMonth()+1).padStart(2, '0')}-${String(tomorrow.getDate()).padStart(2, '0')}`; db.users.aggregate([ { $addFields: { // 构造当前年份的生日日期 birthDate: { $dateFromString: { dateString: { $concat: [ { $toString: new Date().getFullYear() }, "-", { $toString: { $padLeft: ["$aboutPage.birthMonth", 2, "0"] } }, "-", { $toString: { $padLeft: ["$aboutPage.birthDay", 2, "0"] } } ] } } } } }, { $addFields: { // 处理跨年生日:如果当前生日日期已过,自动加一年 adjustedBirthDate: { $cond: { if: { $lt: ["$birthDate", new Date()] }, then: { $add: ["$birthDate", 31536000000] }, // 加一年(毫秒级近似值) else: "$birthDate" } } } }, { $match: { // 匹配adjustedBirthDate等于明日的日期(忽略时间) $expr: { $eq: [ { $dateToString: { format: "%Y-%m-%d", date: "$adjustedBirthDate" } }, tomorrowStr ] } } } ]);
注意:方案一避免了聚合管道的额外计算,查询性能更好,更适合生产环境使用;方案二适合需要生成生日DateTime字段做后续处理的场景。
内容的提问来源于stack exchange,提问作者podeig
相关产品推荐
相关产品推荐

