如何在Mongoose中实现按日期每日自动新增指定Schema的文档记录
Mongoose 实现每日自动新增Salah记录方案
实现思路
核心逻辑是通过定时任务每日零点触发,批量为所有未生成当日记录的用户添加符合Schema要求的Salah记录,同时增加防重复逻辑避免异常场景下生成重复数据。
方案1:内置定时任务(适合单体服务部署)
步骤1:安装定时任务依赖
使用业界常用的node-cron实现定时触发:
npm install node-cron # 或使用yarn yarn add node-cron
步骤2:初始化定时任务
在项目启动入口(如server.js/app.js)中,等待MongoDB连接成功后启动定时任务:
import cron from 'node-cron'; import User from './models/User.js'; // 替换为你自己的User模型路径 const initDailySalahTask = () => { // cron表达式规则:秒 分 时 日 月 周,此处配置为每天零点0分0秒触发 const task = cron.schedule('0 0 0 * * *', async () => { try { // 生成当日零点日期对象,消除时分秒干扰避免日期匹配错误 const today = new Date(); today.setHours(0, 0, 0, 0); // 数据库层面批量更新,性能远高于逐用户查询更新 await User.updateMany( // 筛选条件:仅给还没有当日记录的用户添加,防止重复插入 { 'salahRecord.date': { $ne: today } }, // 向salahRecord数组追加当日默认记录 { $push: { salahRecord: { date: today, fajr: false, dhuhr: false, asr: false, maghrib: false, isha: false } } } ); console.log('今日Salah记录批量生成完成'); } catch (err) { console.error('每日Salah记录生成失败:', err); } }, { // 必须配置正确时区,避免定时触发时间偏移,比如东八区填'Asia/Shanghai',沙特时区填'Asia/Riyadh' timezone: 'Asia/Shanghai' }); task.start(); console.log('每日Salah记录定时任务已启动'); }; export default initDailySalahTask;
在MongoDB连接成功的回调中调用initDailySalahTask()即可启动任务。
可选优化项
1. 新增用户自动生成当日记录
给UserSchema添加预保存中间件,新用户注册时自动生成当日的Salah记录,避免当天零点已过、新用户当日无数据的问题:
UserSchema.pre('save', function(next) { if (this.isNew) { const today = new Date(); today.setHours(0, 0, 0, 0); this.salahRecord.push({ date: today, fajr: false, dhuhr: false, asr: false, maghrib: false, isha: false }); } next(); });
2. Schema加唯一索引防重复
给SalahRecordSchema添加数组内唯一索引,即使定时任务异常重复触发也不会生成重复的日期记录:
SalahRecordSchema.index({ date: 1 }, { unique: true });
注意事项
- 多实例部署场景下不要直接使用内置node-cron,会出现多实例重复执行的问题,建议换成云厂商的定时触发函数(如阿里云函数计算、AWS CloudWatch Events)单独触发更新逻辑,或者加Redis分布式锁避免重复执行。
- 若用户量超过10万,建议分批执行更新操作,避免单次批量更新给数据库造成过大压力。
内容的提问来源于stack exchange,提问作者Basit Minhas
相关产品推荐
相关产品推荐

