如何用MongoDB实现每日0点重置日数据及月末重置月数据?
在MongoDB服务器端实现每日/月末数据重置方案
针对你需要在服务器端自动重置totalOfDay和totalOfMonth的需求,以下是几种可靠的实现方式:
方案1:MongoDB Atlas Triggers(云服务场景)
如果你使用MongoDB Atlas托管数据库,可以直接利用其内置的定时触发器实现无服务器的自动重置:
- 登录Atlas控制台,进入你的项目,选择Database -> Triggers -> Add Trigger
- 配置触发器类型为Scheduled:
- 每日重置:设置调度为
0 0 * * *(UTC时间每日0点,可根据时区调整) - 月末重置:设置调度为
0 0 L * *(UTC时间每月最后一天0点)
- 每日重置:设置调度为
- 在触发器函数中编写重置逻辑:
exports = async function() { const collection = context.services.get("你的集群名称").db("你的数据库名").collection("你的集合名"); // 假设统计数据存在一个固定文档中,比如_id为'system-stats' const now = new Date(); const isEndOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate() === now.getDate(); let updateData = { $set: { totalOfDay: 0 } }; if (isEndOfMonth) { updateData.$set.totalOfMonth = 0; } await collection.updateOne( { _id: 'system-stats' }, updateData, { upsert: true } // 如果文档不存在则创建 ); console.log("数据重置完成"); };
方案2:自建MongoDB + Cron定时脚本(本地/自建服务器场景)
如果是自建MongoDB服务器,结合系统Cron和Node.js脚本实现:
步骤1:编写Node.js重置脚本(reset-stats.js)
const { MongoClient } = require('mongodb'); async function resetStats() { const uri = 'mongodb://你的MongoDB地址:27017'; const client = new MongoClient(uri); try { await client.connect(); const db = client.db('你的数据库名'); const collection = db.collection('你的集合名'); const now = new Date(); const isEndOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate() === now.getDate(); let updateData = { $set: { totalOfDay: 0 } }; if (isEndOfMonth) { updateData.$set.totalOfMonth = 0; } await collection.updateOne( { _id: 'system-stats' }, updateData, { upsert: true } ); console.log(`[${new Date().toISOString()}] 数据重置成功`); } catch (err) { console.error(`[${new Date().toISOString()}] 重置失败:`, err); } finally { await client.close(); } } resetStats();
步骤2:配置Cron定时任务
在Linux服务器上执行crontab -e,添加以下规则:
# 每日0点执行重置脚本 0 0 * * * node /path/to/reset-stats.js >> /path/to/reset-log.log 2>&1
注:月末重置无需单独配置,脚本内已通过日期判断自动处理,避免Cron表达式在部分系统中对
L支持不佳的问题。
方案3:业务逻辑层实时校验(兜底方案)
为了避免定时任务故障导致数据错误,可以在每次读写统计数据时增加实时校验逻辑:
async function getStats() { const collection = db.collection('你的集合名'); const statsDoc = await collection.findOne({ _id: 'system-stats' }); const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const isEndOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate() === now.getDate(); // 检查是否是新的一天,重置totalOfDay if (!statsDoc || statsDoc.lastResetDay < today) { await collection.updateOne( { _id: 'system-stats' }, { $set: { totalOfDay: 0, lastResetDay: today }, ...(isEndOfMonth ? { $set: { totalOfMonth: 0, lastResetMonth: new Date(now.getFullYear(), now.getMonth()) } } : {}) }, { upsert: true } ); return { totalOfDay: 0, totalOfMonth: isEndOfMonth ? 0 : statsDoc?.totalOfMonth || 0 }; } return statsDoc; }
每次获取统计数据时先判断是否需要重置,确保数据准确性。
内容的提问来源于stack exchange,提问作者Vinicius Celestino
相关产品推荐
相关产品推荐

