在 findOneAndUpdate() 之前使用 Mongoose `pre` 钩子获取文档

Mui*_*rik 2 mongoose mongodb

我试图在我的 MongoDB 后端使用 Mongooseprepost钩子,以便比较文档在保存前和保存后的状态,以便根据更改的内容触发其他一些事件。但是到目前为止,我无法通过 Mongoosepre挂钩获取文档。

根据文档“预挂钩对 doc.save() 和 doc.update() 都有效。在这两种情况下,这都是指文档本身......”。所以我这就是我尝试过的。首先在我的模型/模式中,我有以下代码:

let Schema = mongoose
  .Schema(CustomerSchema, {
    timestamps: true
  })
  .pre("findOneAndUpdate", function(next) {
    trigger.preSave(next);
  })
  // other hooks
}
Run Code Online (Sandbox Code Playgroud)

...然后在我的触发器文件中,我有以下代码:

exports.preSave = function(next) {
  console.log("this: ", this);
  }
};
Run Code Online (Sandbox Code Playgroud)

但这是记录到控制台的内容:

这:{ preSave: [Function], postSave: [AsyncFunction] }

所以很明显这是行不通的。这并没有像我希望的那样注销文档。为什么this文档本身不在这里,因为文档本身似乎表明了这一点?有没有办法可以用pre钩子抓住文档?如果没有,人们是否有另一种方法来实现这一目标?

sci*_*lot 11

this由于每种中间件功能的上下文差异而产生了混乱。在文档 pre或中间件期间post,您可以使用this来访问文档模型,但不能在其他挂钩中。

中间件功能有3种,都有前置阶段和后置阶段。

在文档中间件功能中,this指的是文档(模型)。

  • init, validate, save, remove

查询中间件函数中,this指的是查询

  • count,find,findOne,findOneAndRemove,findOneAndUpdate,update

在聚合中间件中,this指的是聚合对象。

  • aggregate

这里解释了https://mongoosejs.com/docs/middleware.html#types-of-middleware

因此,您可以在 期间轻松访问该文档 pre("init"), pre("init"), pre("validate"), post("validate"), pre("save"), post("save"), pre("remove"), post("remove"),但不能在任何其他时间访问该文档。

我见过人们在其他中间件挂钩中进行更多查询以再次找到模型的示例,但这对我来说听起来相当危险。

简短的答案似乎是,您需要将原始查询更改为面向文档的查询,而不是查询或聚合样式。这看起来确实是一个奇怪的限制。


Har*_*lis 9

您无法检索pre挂钩中的文档。

根据文档 pre是一个查询中间件,this指的是查询而不是正在更新的文档。

  • Haris 是正确的,[the docs](https://mongoosejs.com/docs/middleware.html#types-of-middleware) 将 `findOneAndUpdate` 列为查询中间件(`update` 也是如此)。事实是,这些方法根本无法访问正在更新的文档。 (3认同)

AB'*_*AB' 9

根据文档,您预挂钩无法获取函数中的文档,但它可以获取如下查询

schema.pre('findOneAndUpdate', async function() { 
 const docToUpdate = await this.model.findOne(this.getQuery());
 console.log(docToUpdate); // The document that findOneAndUpdate() will modify
});
Run Code Online (Sandbox Code Playgroud)