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

如何为Mongoose Schema子字段添加独立时间戳?

为Mongoose Schema子字段添加独立时间戳的正确方案

嘿,我来帮你理清这个问题。首先要明确:直接在嵌套的generate/verify子字段里写{timestamps: true}是既语法错误又不生效的——Mongoose的timestamps选项是Schema级别的配置,只能用于顶级Schema或者独立定义的子文档Schema,不能直接嵌套在普通的对象型字段里,而且你写的那种语法(对象里直接放无键名的对象)本身就会导致JS语法报错。

下面给你两种靠谱的实现方案,根据你的需求选就行:

方案一:手动维护时间戳(适合简单场景)

如果你的需求比较简单,不想额外定义子Schema,可以在更新generate或verify字段的时候,手动设置createdAt和updatedAt:

比如生成OTP时的更新逻辑:

// 更新generate字段的时间戳和其他属性
await User.findOneAndUpdate(
  { email: targetEmail },
  {
    $set: {
      'mobileNumber.otp.generate.attempts': 1, // 示例更新attempts
      'mobileNumber.otp.generate.total': 1,
      'mobileNumber.otp.generate.updatedAt': new Date()
    },
    // 只有第一次生成时才设置createdAt
    $setOnInsert: {
      'mobileNumber.otp.generate.createdAt': new Date()
    }
  },
  { upsert: true, new: true }
);

验证OTP时同理,更新verify字段的updatedAt(首次验证时设置createdAt)。这种方式的好处是灵活,不需要额外的Schema定义,但缺点是每次操作都要手动处理时间戳,容易遗漏。

方案二:用子文档Schema自动维护时间戳(推荐)

这是更符合Mongoose最佳实践的方式——把generate和verify分别定义成独立的子文档Schema,然后在子Schema里设置timestamps: true,这样Mongoose会自动帮你维护这两个时间戳:

// 定义OTP生成的子Schema
const otpGenerateSchema = new mongoose.Schema({
  attempts: { type: Number, default: 0 },
  total: { type: Number, default: 0 }
}, { timestamps: true }); // 这里设置timestamps,自动生成createdAt和updatedAt

// 定义OTP验证的子Schema
const otpVerifySchema = new mongoose.Schema({
  attempts: { type: Number, default: 0 },
  total: { type: Number, default: 0 }
}, { timestamps: true });

// 主用户Schema
const userSchema = new mongoose.Schema({
  email: { type: String, unique: true },
  name: { type: String },
  mobileNumber: {
    isVerified: { type: Boolean, default: false },
    otp: {
      generate: otpGenerateSchema, // 使用子Schema
      verify: otpVerifySchema
    }
  }
}, { timestamps: true }); // 主Schema的时间戳依然保留

这样一来,每当你更新generate或verify字段时,Mongoose会自动更新对应的updatedAt,而首次创建时会自动设置createdAt,完全不用手动处理,非常省心。

补充说明

  • 子文档Schema的timestamps生成的字段名默认就是createdAt和updatedAt,和主Schema保持一致,如果你想自定义字段名,可以写成{ timestamps: { createdAt: 'genCreatedAt', updatedAt: 'genUpdatedAt' } }这样的形式。
  • 如果你用子文档Schema的方式,查询出来的文档里,generate和verify会是Mongoose的子文档对象,拥有子文档的方法,但日常的读写操作和普通对象几乎没有区别。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 15:27:49