You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

每日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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 04:40:34