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

如何每日自动重置MongoDB Activity文档的totalFocusDay字段?

实现每日自动重置totalFocusDay的两种可行方案

方案一:惰性更新(推荐,无需额外维护定时任务)

这种思路是每次操作文档时自动检查是否需要重置,不用单独跑定时任务,对小项目或资源有限的场景更友好。

具体实现:

给Activity模型添加一个自定义静态方法,专门处理获取文档并自动重置的逻辑:

const mongoose = require("mongoose");

const activitySchema = new mongoose.Schema({
  totalHours: {
    type: Number,
    default: 0
  },
  totalFocusDay: {
    type: Number,
    default: 0
  },
  totalActiveDay: {
    type: Number,
    default: 0
  },
},
{
  timestamps: true,
}
);

// 自定义静态方法:获取文档前先检查并重置符合条件的记录
activitySchema.statics.getAndReset = async function(docId) {
  const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
  // 先更新满足条件的文档:updatedAt早于24小时前的,重置totalFocusDay并更新时间
  await this.updateOne(
    { _id: docId, updatedAt: { $lt: twentyFourHoursAgo } },
    { $set: { totalFocusDay: 0 }, $currentDate: { updatedAt: true } }
  );
  // 返回更新后的文档
  return this.findById(docId);
};

module.exports = mongoose.model("Activity", activitySchema);

之后业务代码里不用直接调用findById,改用这个自定义方法即可:

const Activity = require('./models/Activity');

// 获取目标文档并自动处理重置逻辑
const targetActivity = await Activity.getAndReset('目标文档ID');

如果想让所有findOne查询都自动触发检查,也可以用mongoose的前置中间件:

// 给findOne添加前置钩子,查询前自动重置符合条件的文档
activitySchema.pre('findOne', async function(next) {
  const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
  // 对当前查询范围内的文档批量检查并重置
  await this.model.updateMany(
    { ...this.getQuery(), updatedAt: { $lt: twentyFourHoursAgo } },
    { $set: { totalFocusDay: 0 }, $currentDate: { updatedAt: true } }
  );
  next();
});

方案二:定时批量更新(适合主动重置场景)

如果需要每天固定时间(比如凌晨0点)批量重置所有符合条件的文档,可以用node-schedule实现定时任务。

步骤:

  1. 安装依赖:
npm install node-schedule
  1. 编写定时任务脚本:
const schedule = require('node-schedule');
const Activity = require('./models/Activity');

// 每天凌晨0点执行重置任务(cron表达式格式:分 时 日 月 周)
const resetJob = schedule.scheduleJob('0 0 * * *', async () => {
  const twentyFourHoursAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
  // 批量更新所有超过24小时未更新的文档
  const updateResult = await Activity.updateMany(
    { updatedAt: { $lt: twentyFourHoursAgo } },
    { $set: { totalFocusDay: 0 }, $currentDate: { updatedAt: true } }
  );
  console.log(`每日重置完成:共修改${updateResult.modifiedCount}条文档`);
});

console.log('每日重置任务已启动');
  1. 在项目启动时引入该脚本,确保定时任务持续运行。

关键细节提醒

  • 使用$currentDate更新updatedAt,能确保时间为MongoDB服务器的当前时间,避免客户端时间不一致的问题。
  • 生产环境中,Node.js定时任务可能因服务重启中断,这种情况可以考虑使用MongoDB Atlas的定时触发器,稳定性更高。

内容的提问来源于stack exchange,提问作者Mohamed Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 11:10:29