【问题标题】:How to add timestamps to mongoose schema subfields?如何将时间戳添加到猫鼬模式子字段?
【发布时间】:2020-11-08 15:11:06
【问题描述】:

我正在尝试在generate: {}verify:{}otp 的子字段中添加createdAtupdatedAt 时间戳

我知道使用{ timestamps: true } 会将createdAtupdatedAt 时间戳添加到整个架构中。`

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

【问题讨论】:

    标签: mongodb mongoose mongoose-schema


    【解决方案1】:

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

    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
    }
    

    【讨论】:

    • OP 问题特定于子字段:在这种情况下是否有效?
    【解决方案2】:

    好的,看来这个答案变得更受欢迎了,所以我们将对其进行全面覆盖。

    {timesamps: true} 做什么以及它是如何做的?

    {timesamps: true}的原始代码,来自 mongoose.js 可以找到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(object)和find({}).lean()的js-Object/JSON/result有很大区别

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

    请确定:当您使用 .find 而不使用 .lean() 选项时,您正在处理 MongooseDocument(s),但如果启用它,您将收到纯 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 选项相同的结果,但您可以将其应用于架构中的每个子文档。

    【讨论】:

    • 您好,如何通过$set 更新时间戳?我应该这样做吗? userSchema.pre('save', function(next) { this.updatedAt = Date.now(); return next(); });
    • @TamashiKaizen 我更新了我的原始答案以避免误解。您可以使用更新查询更新字段updatedAt,或使用setters 来获得相同的结果。但无需修改您自己的查询。
    【解决方案3】:

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

    您可能希望创建两个具有 OneToMany 关系的其他实体 - AttributeAttributeValue,以跟踪值更改时间戳。

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

    【讨论】:

      【解决方案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 });
      

      【讨论】:

      • 如何更改时间戳 createdAt 和 updatedAt 格式就像 (DD-MM-YYYY HH:mm:ss)
      猜你喜欢
      • 1970-01-01
      • 2023-04-07
      • 2017-04-22
      • 1970-01-01
      • 2018-11-28
      • 2015-04-11
      • 1970-01-01
      相关资源
      最近更新 更多