TypeScript Express下MongoDB生日查询方案(禁用$where)
解决MongoDB查询生日的问题
核心错误说明
你当前的代码有两个关键问题:
- 不能直接在
find的字段条件中使用$month、$dayOfMonth这类聚合操作符,必须用$expr包裹聚合表达式才能在查询条件里生效。 - 日期方法用错:
today.getDay()是获取星期几(0-6),要获取当月日期得用today.getDate();另外JavaScript的getMonth()返回0-11,而MongoDB的$month返回1-12,需要加1转换。
仅比较日和月查询生日(以今天为例)
用$expr包裹聚合表达式,直接匹配生日的月和日:
const today = new Date(); // 转换为MongoDB的月份格式(1-12) const currentMonth = today.getMonth() + 1; const currentDay = today.getDate(); const presentEvent = await User.find({ $expr: { $and: [ { $eq: [{ $month: "$dob" }, currentMonth] }, { $eq: [{ $dayOfMonth: "$dob" }, currentDay] } ] } });
查询过去10天+未来10天的生日(处理跨年情况)
需要考虑跨年场景(比如12月末查未来10天会包含次年1月的生日),用$concat、$padStart将日期转为MM-DD格式字符串进行范围匹配:
const today = new Date(); // 计算过去10天和未来10天的日期 const past10Days = new Date(today); past10Days.setDate(today.getDate() - 10); const future10Days = new Date(today); future10Days.setDate(today.getDate() + 10); // 把Date转为"MM-DD"格式字符串(用于生成基准范围值) const formatMD = (date: Date) => { const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${month}-${day}`; }; const past10MD = formatMD(past10Days); const future10MD = formatMD(future10Days); // MongoDB聚合表达式:将dob字段转为"MM-DD"字符串 const dobMDExpr = { $concat: [ { $toString: { $padStart: [{ $month: "$dob" }, 2, "0"] } }, "-", { $toString: { $padStart: [{ $dayOfMonth: "$dob" }, 2, "0"] } } ] }; let birthdayQuery; // 判断是否跨年:如果过去10天的MM-DD大于未来10天的,说明跨年度 if (past10MD > future10MD) { birthdayQuery = { $expr: { $or: [ { $gte: [dobMDExpr, past10MD] }, { $lte: [dobMDExpr, future10MD] } ] } }; } else { // 不跨年情况,直接匹配范围 birthdayQuery = { $expr: { $and: [ { $gte: [dobMDExpr, past10MD] }, { $lte: [dobMDExpr, future10MD] } ] } }; } const recentBirthdays = await User.find(birthdayQuery);
内容的提问来源于stack exchange,提问作者user19742850
相关产品推荐
相关产品推荐

