使用Mongoose查找timeExpired大于当前时间的文档实现标签自动删除
你的代码存在以下几处核心问题:
setInterval传参错误:你传入的是autoDeleteTag(),这会直接执行一次函数并将返回值传给定时器,后续定时器不会再执行定时逻辑。正确写法是传入函数引用autoDeleteTag(不带括号)。- 数据库操作是异步逻辑,你用同步写法无法拿到正确的查询结果:MongoDB的
findOne、delete都是异步方法,需要用async/await处理异步返回,否则你拿到的findTag是Promise对象而非查询结果,判断逻辑完全失效。 - 查询条件完全错误:你的需求是删除已经到期的标签,也就是
timeExpired(到期时间戳)小于等于当前时间的记录,你写的是等于当前时间戳,定时器100ms执行一次,刚好命中毫秒级完全相等的记录概率极低,绝大多数到期记录都不会被匹配到。 - 执行逻辑效率低:你现在是查一条删一条,完全可以直接用
deleteMany批量删除所有到期记录,不需要单独查询再操作。 - 定时器间隔设置不合理:100ms查询一次数据库过于频繁,对于30天到期的场景,间隔设为10分钟甚至1小时都完全够用,过高的查询频率只会浪费数据库性能。
修正后代码示例
// 函数改为async异步函数 const autoDeleteTag = async function () { const currentTime = Date.now() // 直接批量删除所有到期的记录,不需要先查询 await tagSchema.deleteMany({ timeExpired: { $lte: currentTime } }) } // 传入函数引用,间隔改为10分钟(单位是毫秒,10*60*1000=600000),可根据需求调整 setInterval(autoDeleteTag, 600000) // 启动时先执行一次,避免程序刚启动时到期的记录要等下一轮定时才会被删 autoDeleteTag()
补充优化建议:如果你使用的是Mongoose操作MongoDB,更推荐直接用TTL索引实现自动过期删除,不需要自己维护定时任务,可靠性更高:
const tagSchema = new mongoose.Schema({ // 其他字段... timeExpired: { type: Date, // 这里直接存Date类型就行,不用存时间戳,MongoDB会自动处理 index: { expires: 0 } } })配置完成后MongoDB会自动在后台清理到期的文档,不需要自己写定时任务逻辑。
内容的提问来源于stack exchange,提问作者KanPots
相关产品推荐
相关产品推荐

