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

时间:2019-02-07 18:13:46

标签: mongodb mongoose

我试图在MongoDB后端中使用Mongoose prepost钩子,以便比较文档在保存前和保存后的状态,从而根据事件触发其他事件改变了。但是到目前为止,我仍然无法通过Mongoose pre钩子获取文档。

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

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

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

exports.preSave = function(next) {
  console.log("this: ", this);
  }
};

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

  

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

很明显,这没有用。这并没有注销我希望的文件。为什么this不能像文档本身所示那样在这里显示文档本身?有没有一种方法可以使我使用pre钩子来保存文档?如果没有,人们是否曾经使用另一种方法来实现这一目标?

3 个答案:

答案 0 :(得分:2)

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

根据documentation pre是查询中间件,而this是指查询而不是要更新的文档。

答案 1 :(得分:2)

由于每种中间件功能中this上下文的不同而引起混乱。在文档 prepost中间件期间,您可以使用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")期间访问文档,而不能访问其他任何文件。

我已经看到一些例子,人们在其他中间件挂钩中进行更多查询,以再次找到模型,但这对我来说听起来很危险。

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

答案 2 :(得分:2)

根据文档,您预钩子无法使文档生效,但可以按如下方式获取查询

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