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

如何在Node.js与Mongoose中实现定时自动插入数据?

在Node.js + Mongoose中实现定时自动插入数据(每月末为例)

实现这类定时任务最常用的方案是借助Node.js的定时任务库,下面以node-schedule和node-cron两个主流库为例,给出具体实现步骤:

方案一:使用node-schedule(直观的时间规则定义)

1. 安装依赖

npm install node-schedule
# 或 yarn add node-schedule

2. 编写定时任务逻辑

假设你有两个Mongoose模型:

  • CurrentData:存储实时业务数据
  • MonthlyArchive:用于存储每月末归档的数据

示例代码:

const schedule = require('node-schedule');
const mongoose = require('mongoose');
const CurrentData = require('./models/CurrentData'); // 引入你的模型
const MonthlyArchive = require('./models/MonthlyArchive');

// 定义每月末23:59:59的执行规则
const monthlyEndRule = new schedule.RecurrenceRule();
monthlyEndRule.date = null; // null 代表每月最后一天
monthlyEndRule.hour = 23;
monthlyEndRule.minute = 59;
monthlyEndRule.second = 59;
monthlyEndRule.tz = 'Asia/Shanghai'; // 按需设置时区,避免服务器时区偏差

// 创建定时任务
schedule.scheduleJob(monthlyEndRule, async () => {
  try {
    // 1. 检查当月是否已完成归档(避免重复执行)
    const today = new Date();
    const currentMonth = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}`;
    const existingArchive = await MonthlyArchive.findOne({ archivedMonth: currentMonth });
    
    if (existingArchive) {
      console.log(`当月(${currentMonth})已完成归档,跳过执行`);
      return;
    }

    // 2. 获取需要归档的当前数据
    const currentRecords = await CurrentData.find({});

    // 3. 转换数据格式并插入归档集合
    const archivePromises = currentRecords.map(record => {
      return MonthlyArchive.create({
        archivedMonth: currentMonth,
        originalData: record.toObject(), // 转换为普通对象存储
        archivedAt: new Date()
      });
    });

    await Promise.all(archivePromises);
    console.log(`当月(${currentMonth})数据归档完成,共归档${currentRecords.length}条数据`);
  } catch (error) {
    console.error('月末归档任务执行失败:', error);
    // 这里可以添加告警逻辑(比如邮件、企业微信通知)
  }
});

方案二:使用node-cron(基于Cron表达式)

1. 安装依赖

npm install node-cron
# 或 yarn add node-cron

2. 编写定时任务逻辑

Cron表达式59 23 L * *代表每月最后一天的23:59执行任务:

const cron = require('node-cron');
const mongoose = require('mongoose');
const CurrentData = require('./models/CurrentData');
const MonthlyArchive = require('./models/MonthlyArchive');

// 定义Cron定时任务
cron.schedule('59 23 L * *', async () => {
  try {
    const today = new Date();
    const currentMonth = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}`;
    const existingArchive = await MonthlyArchive.findOne({ archivedMonth: currentMonth });
    
    if (existingArchive) {
      console.log(`当月(${currentMonth})已归档,跳过`);
      return;
    }

    const currentRecords = await CurrentData.find({});
    const archivePromises = currentRecords.map(record => {
      return MonthlyArchive.create({
        archivedMonth: currentMonth,
        originalData: record.toObject(),
        archivedAt: new Date()
      });
    });

    await Promise.all(archivePromises);
    console.log(`当月(${currentMonth})归档完成,${currentRecords.length}条数据入库`);
  } catch (error) {
    console.error('归档任务出错:', error);
  }
}, {
  timezone: 'Asia/Shanghai' // 指定时区
});

关键注意事项

  • 进程守护:确保Node.js进程持续运行,生产环境建议用PM2、systemd等工具守护进程,避免进程意外退出导致定时任务失效。
  • 幂等性:每次执行任务前先检查是否已完成当月归档,避免服务器重启或任务重复触发导致数据重复插入。
  • 错误处理:必须捕获异步操作的异常,避免单个任务失败导致整个定时任务崩溃,必要时添加告警机制。
  • 性能优化:如果数据量很大,不要一次性查询所有数据,建议用分页查询分批处理,避免内存溢出。

内容的提问来源于stack exchange,提问作者jee chang wook

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:54:20