每日19-20点ET时段Mongoose的getUTCDate()查询异常问题
问题根源
你遇到的重复文档问题,核心是Mongoose对象类型默认值的执行时机错误:
- 当前Schema中
dateInfo的默认值是直接定义的对象,里面的year/month/day/date都是在Schema加载(服务器启动)时就计算完成的固定值,而非每次创建文档时动态生成当前UTC日期。 - 服务器运行超过一天后,新建文档的
dateInfo还停留在启动时的日期,导致你用当前UTC日期查询时找不到对应文档,进而重复创建。 - 美东时间19:00-20:00的问题,是因为该时间段对应UTC的23:00-次日00:00(夏令时),此时查询用的是次日UTC日期,但默认值还是前一天的UTC日期,完全不匹配,所以短时间内生成大量重复文档。
- 你看到的“默认值创建的文档日期差1小时”,本质是默认值为旧的固定值,和当前UTC日期不匹配导致的错觉。
解决方案
1. 修复dateInfo默认值的动态生成逻辑
把dateInfo的默认值改成函数返回对象,确保每次创建文档时都重新计算当前UTC日期:
const statsSchema = new mongoose.Schema({ dateInfo: { type: Object, required: true, default: function() { // 改用普通函数返回动态值,不能用箭头函数 const now = new Date(); return { date: new Date(Date.now()), year: now.getUTCFullYear(), month: now.getUTCMonth() + 1, day: now.getUTCDate() }; }, }, timeSpent: { type: Number, required: false, default: 0 } });
2. 统一查询与创建的日期计算逻辑
把UTC日期计算抽成公共函数,避免查询和默认值的逻辑差异:
// 公共函数:获取当前UTC的年月日信息 function getUTCDateInfo() { const now = new Date(); return { year: now.getUTCFullYear(), month: now.getUTCMonth() + 1, day: now.getUTCDate() }; } // 查询时复用该函数 const dateInfo = getUTCDateInfo(); let stats = await Statistics.findOne({ 'dateInfo.year': dateInfo.year, 'dateInfo.month': dateInfo.month, 'dateInfo.day': dateInfo.day }); // 手动创建文档时也用同一个函数 if (!stats) { stats = new Statistics({ dateInfo: getUTCDateInfo() }); }
3. 添加复合唯一索引防止重复
给dateInfo的年月日字段添加复合唯一索引,即使查询逻辑出错,MongoDB也会直接阻止重复文档生成:
statsSchema.index( { 'dateInfo.year': 1, 'dateInfo.month': 1, 'dateInfo.day': 1 }, { unique: true } );
内容的提问来源于stack exchange,提问作者shaedopotato
相关产品推荐
相关产品推荐

