Mongodb 如何向mongoose模式子字段添加时间戳?

Mongodb 如何向mongoose模式子字段添加时间戳?,mongodb,mongoose,mongoose-schema,Mongodb,Mongoose,Mongoose Schema,我试图在generate:{}和verify:{}中的otp子字段中添加createdAt和updatedAt时间戳 我知道使用{timestamps:true}会将createdAt和updatedAt时间戳添加到整个模式中` const userSchema = new mongoose.Schema({ email: { type: String, unique: true }, name: { type: String }, mobileNumber:

我试图在
generate:{}
verify:{}
中的
otp
子字段中添加
createdAt
updatedAt
时间戳

我知道使用
{timestamps:true}
会将
createdAt
updatedAt
时间戳添加到整个模式中`

const userSchema = new mongoose.Schema({    
    email: { type: String, unique: true },
    name: { type: String }, 
    mobileNumber: {
        isVerified: {type: Boolean, default: false},
        otp: {
            generate: {
              attempts: {type: Number, default: 0},
              total: {type: Number, default: 0},
              createdAt: {type: Date},
              updatedAt: {type: Date}
            },
            verify: {
              attempts: {type: Number, default: 0},
              total: {type: Number, default: 0},
              createdAt: {type: Date},
              updatedAt: {type: Date}
            }
          }
    }
}, { timestamps: true });
向子字段添加单个时间戳的正确解决方案是什么?向子字段添加
{timestamps:true}
是否正确

            generate: {
              attempts: {type: Number, default: 0},
              total: {type: Number, default: 0},
              {timestamps: true}
            },
            verify: {
              attempts: {type: Number, default: 0},
              total: {type: Number, default: 0},
              {timestamps: true}
            }

您必须为子字段定义单独的模式,然后将其用作子字段的类型

const otpSchema = new mongoose.Schema({    
    attempts: { type: Number, default: 0 },
    total: { type: Number, default: 0 }
}, {
    _id: false, // omit _id fields for subfields
    timestamps: true // timestamps options for subfields
});

const userSchema = new mongoose.Schema({    
    email: { type: String, unique: true },
    name: { type: String }, 
    mobileNumber: {
        isVerified: { type: Boolean, default: false },
        otp: {
            generate: otpSchema, // use the defined schema
            verify: otpSchema
        }
    }
}, { timestamps: true });
好吧,这个答案似乎变得更受欢迎了,所以一份遗嘱将其扩展到了全覆盖范围

{timesamps:true}
做什么?它是如何做的? 可以找到mongoose.js中的原始
{timesamps:true}
代码

如何准确地
timestamps:true}
知道何时以及如何更新
updatedAt
字段,而不更新
createdAt

根据该守则:

  this.pre('save', function(next) {
    
    /**
    * SKIP CODE A BIT
    */

    if (!skipUpdatedAt && updatedAt && (this.isNew || this.isModified())) {
      let ts = defaultTimestamp;
      if (this.isNew) {
        if (createdAt != null) {
          ts = this.$__getValue(createdAt);
        } else if (auto_id) {
          ts = this._id.getTimestamp();
        }
      }
      this.set(updatedAt, ts);
    }

    next();
  });

因此,每次都会执行此代码(当然,如果时间戳设置为
true

MongooseDocument(object)和js object/JSON/result of
find({}).lean()之间有很大区别

您可以在MongooseDocument上强制转换各种方法,例如(这正是mongoose理解
updatedAt
字段应该更新,而
createdAt
不应该更新的方式)。或者将其转换为
.toObject()
.toJSON()
方法的完整列表

请确定:当您在不使用
.lean()
选项的情况下使用
.find
时,您正在处理MongooseDocument,但如果启用它,您将收到纯JavaScript对象

如何为自己的模式创建自己的
{timestamps:true}
实现? 通过
default
值和在模式中使用
setters
可以轻松获得相同的结果:

  createdAt: {type: Date, default: Date.now},
  updatedAt: {type: Date, default: Date.now, set: v => v.Date.now()}
你可以阅读

此外,它可以是您想要的任何函数,例如,您可以每次在任何insert | | modify操作(以及
update
)上修改值

..或者您可以避免设置器,每次都通过:
model.findAndUpdate({your_字段:value},{your_字段:value,updatedAt:Date.now())手动更新代码中的
updatedAt
字段


因此,最终,使用setter(或手动查询更新)将为您提供与
timestamps:true
选项相同的结果,但您可以将其应用于模式中的每个子文档。

我认为此类功能不属于要提供的数据库功能范围,也不属于要启用的mongoose

您可能需要创建另外两个实体-
Attribute
AttributeValue
OneToMany关系,以跟踪值更改时间戳


嗯,这就是我们在我当前的主要项目中解决这个问题的方法。

我遇到了同样的问题,我的解决方案非常简单

const userSchema = mongoose.Schema({ email: String }, { timestamps: true });
自动添加createdAt和updatedAt的我的结果:

{
   "_id" : ObjectId("60ba2cb3bca3572f6ca1b525"),
   "title" : "First post with timestamp",
   "content" : "Test post timestamp",
   "createdAt" : ISODate("2021-06-04T13:37:55.025Z"),
   "updatedAt" : ISODate("2021-06-04T13:37:55.025Z"),
   "__v" : 0
}

您好,如何通过
$set
更新时间戳?我应该这样做吗?
userSchema.pre('save',function(next){this.updatedAt=Date.now();return next();})
@TamashiKaizen为了避免误解,我更新了我的原始答案。你可以用你的更新查询更新字段
updatedAt
,或者使用
setters
来获得相同的结果。但是不修改你自己的查询。OP问题是针对子字段的:这种情况下有效吗?