如何为猫鼬模式子字段添加时间戳?

时间:2020-07-19 06:58:39

标签: mongodb mongoose mongoose-schema

我正在尝试在createdAtupdatedAt的{​​{1}}的子字段中添加otpgenerate: {}时间戳

我知道使用verify:{}会将{ 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}

4 个答案:

答案 0 :(得分:4)

您必须为子字段定义一个单独的架构,然后将其用作子字段的类型。

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 });

答案 1 :(得分:2)

好吧,这个答案似乎变得越来越流行,因此a会扩展其覆盖范围。

{timesamps: true}的工作方式以及工作方式?

可从mongoose.js找到原始的{timesamps: true}代码here @ line:1150

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();
  });

因此,每次when mongoose driver triggers .save on MongooseDocument都会执行此代码(当然,如果时间戳设置为true

MongooseDocument(对象)与js-Object / JSON / find({}).lean()的结果之间有很大的区别

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

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

如何为自己的模式创建{timestamps: true}的实现?

通过default值并在模式中使用setters,很容易获得相同的结果:

  createdAt: {type: Date, default: Date.now},
  updatedAt: {type: Date, default: Date.now, set: v => v.Date.now()}

您可以阅读more about setters here

也可以是您想要的任何函数,例如,您可以每次在任何插入||上修改值。修改操作(还有update

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

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

答案 2 :(得分:1)

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

您可能要创建另外两个具有 OneToMany 关系的实体AttributeAttributeValue,以跟踪值的更改时间戳。

好吧,这就是我们在当前主要项目中解决问题的方式。

答案 3 :(得分:0)

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

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
}
相关问题