【问题标题】:How to check modified fields in pre/post update hook in Mongoose.js如何在 Mongoose.js 的更新前/更新后挂钩中检查修改后的字段
【发布时间】:2018-03-17 07:32:34
【问题描述】:

我需要知道修改过的字段,或者是否在 prepost update 钩子中修改了 Mongoose 架构中的特定字段。 我尝试了以下方法,但仍然无法弄清楚:

schema.post('update', function (doc) {
    //check modified fields or if the name field was modified and then update doc
});

我知道 pre save 中可能有一个 isModified 方法,但我不知道如何对 更新挂钩。 任何建议将不胜感激。

【问题讨论】:

    标签: javascript node.js mongodb mongoose mongoose-schema


    【解决方案1】:

    看看:

    http://mongoosejs.com/docs/api.html#document_Document-modifiedPaths

    返回修改后的路径数组。

      schema.pre('save', function (next) {
        //check modified fields or if the name field was modified and then update doc
        var modified_paths = this.modifiedPaths();
        next();
      })
    

    【讨论】:

    • 返回TypeError: doc.modifiedPaths is not a function doc中没有名为modifiedPaths的函数
    • 我的错误。 modifiedPaths 似乎在 post 中间件中不可用。已更新答案。
    • 我知道 pre save 钩子中有这样的功能,但正如我在问题中提到的,我需要检查 中的更新字段前/后更新挂钩。 理解?
    【解决方案2】:

    如果你想知道你正在修改哪些字段,那么你需要通过调用save发出一个update命令:

    Tank.findById(id, function (err, tank) {
      if (err) return handleError(err);
    
      tank.set({ size: 'large' });
      tank.save(function (err, updatedTank) {
        if (err) return handleError(err);
        res.send(updatedTank);
      });
    });
    

    这样 pre-save 钩子将被调用,您将可以访问:

    Document.prototype.modifiedPaths()
    

    因为 pre-save 钩子中的this 引用了文档:

    TankSchema.pre('save', function (next) {
      // ...
      this.modifiedPaths();
      // ...
    });
    

    另一方面,通过调用update 发出update 命令时,您将无法获得相同的结果:

    Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);
    

    因为在调用 update 时,文档挂钩(例如 pre-savepost-save)根本没有被执行。在这种情况下,查询挂钩正在被执行(例如pre-updatepost-update)。 查询钩子的问题是它们里面的this没有引用文档,所以this.modifiedPaths === undefined

    schema.post('update', function (doc) {
      // `this` refers to model.Query
      // `doc` refers to CommandResult 
    });
    

    【讨论】:

      【解决方案3】:

      试试看:

       schema.post('update', function () {
           const modifiedFields = this.getUpdate().$set;
           // ...
       });
      

      【讨论】:

      • 这不是一个答案,您在 $set of update 中输入的任何字段都会列在那里,无论它们与旧值有什么不同或相同。
      【解决方案4】:

      没有直接的方法。 mongoose 正在跟踪一个名为 isNew 的变量,以检查是否创建了新文档。

      有关 Document#isNew 的信息,请参阅 Document#isNew

      但是,您可以创建自己的跟踪器来检查保存后挂钩以识别文档是否已更新。

      schema.pre('save', function (doc) {
          this.isDocUpdated = false;
          if (this.isModified()) {
              this.isDocUpdated = true;
          }
      });
      
      schema.post('save', function (doc) {
          if (this.isDocUpdated) {
              console.log('post save hook called');
          }
      });
      

      【讨论】:

      • 您的代码中有错字。第二个钩子应该是'post'而不是'pre'
      • 非常有帮助的答案!
      【解决方案5】:

      对于post()

      Schema.post('update', function () {
              const modifiedFields = this.getUpdate().$set;
              console.log(modifiedFields);
      });
      

      对于pre()

      schema.pre('update', function () {
              const modifiedFields = this.getUpdate();
              delete modifiedFields['$set'];
              delete modifiedFields['$setOnInsert'];
              console.log(modifiedFields);
      });
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-18
        • 1970-01-01
        • 2014-04-15
        • 2021-04-14
        • 2022-11-02
        • 2016-01-10
        • 2014-02-28
        相关资源
        最近更新 更多