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

如何在MongoDB中为存储的OTP等特定数据设置1分钟过期?

在Mongoose用户模型中实现OTP自动过期的方案

当然可以实现OTP的自动过期,不过需要注意MongoDB的TTL索引特性限制,下面针对你的代码问题给出两种可行方案:

先修正当前代码的两个问题

  1. createdAt 默认值用 Date() 会生成字符串而非Date对象,需改为 Date.now 或函数式生成
  2. 模块级的 currentTime 只会在服务启动时计算一次,无法动态生成每个OTP的过期时间,需改为动态计算

方案1:使用独立OTP集合(推荐)

MongoDB的TTL索引只能针对整个文档生效,无法单独删除数组中的子文档。因此最合理的方式是将OTP单独存储为一个集合,利用TTL索引自动删除过期记录,不影响用户主文档。

const mongoose = require("mongoose");

// 单独的OTP模型
const otpSchema = new mongoose.Schema({
  userId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "user",
    required: true
  },
  otp: {
    type: String,
    required: true
  },
  createdAt: {
    type: Date,
    default: Date.now,
    index: { expires: '1m' } // 配置1分钟后自动过期
  }
});

const OtpModel = mongoose.model("Otp", otpSchema);
module.exports = OtpModel;

使用方式:

  • 生成OTP时,创建一条Otp文档关联对应用户
  • 验证OTP时,查询是否存在未过期的记录
  • 验证成功后可手动删除该OTP记录

方案2:在用户模型中手动清理过期OTP

如果必须将OTP存在用户文档的数组中,需要手动清理过期的子文档:

第一步:修正用户模型的日期字段

const mongoose = require("mongoose");

const userSchema = new mongoose.Schema(
  {
    fullName: { type: String, required: false },
    email: { type: String, required: false },
    mobile_number: { type: String, required: false },
    password: { type: String, required: false },
    otp_instance: [{
      otp_id: { type: mongoose.Schema.Types.ObjectId, required: false },
      otp: { type: String, required: false },
      createdAt: {
        type: Date,
        default: Date.now // 生成Date类型的当前时间
      },
      expiration_time: {
        type: Date,
        default: () => new Date(Date.now() + 60 * 1000) // 动态计算1分钟后时间
      }
    }],
    resetLink: { type: String, required: false },
    isAccountVerified: { type: String, required: false },
    token: { type: String, required: false },
    activeStatus: { type: String, required: false, default: "0" },
    deletedStatus: { type: String, required: false, default: "0" },
  },
  { timestamps: true }
);

// 添加清理过期OTP的实例方法
userSchema.methods.cleanExpiredOtp = async function() {
  await this.updateOne({
    $pull: {
      otp_instance: { expiration_time: { $lt: new Date() } }
    }
  });
};

const userModel = mongoose.model("user", userSchema);
module.exports = userModel;

第二步:使用时清理过期OTP

每次添加新OTP前,先清理用户的过期记录:

// 示例:给用户添加新OTP
const user = await userModel.findById(userId);
await user.cleanExpiredOtp();
user.otp_instance.push({ otp: "123456" });
await user.save();

可选:定时全局清理

如果需要批量清理所有用户的过期OTP,可添加定时任务:

// 每分钟执行一次清理
setInterval(async () => {
  await userModel.updateMany(
    {},
    { $pull: { otp_instance: { expiration_time: { $lt: new Date() } } } }
  );
}, 60 * 1000);

内容的提问来源于stack exchange,提问作者sAcHiN pAtEl

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 19:15:55