Mongo`pre`挂钩未按`save()`操作的预期进行触发

时间:2019-02-20 13:31:30

标签: mongodb mongoose

我在MongoDB / Node后端中使用了prepost钩子,以便比较文档的保存前和保存后版本,因此我可以通过基于发生了什么变化。在我的一个模型/集合中,这是有效的,但在另一个模型/集合中,它却没有按预期的方式工作,我不确定为什么。

在有问题的情况下,一些研究已经确定,即使我在使用pre的操作上调用save()钩子触发器,当我控制通过该{{ 1}}钩子,已经应用了更改。换句话说,根据我的判断,该钩子不是在pre操作之前触发,而是在之后触发。

这是我的相关型号代码:

save()

我正在执行的let Schema = mongoose .Schema(CustomerSchema, { timestamps: true }) .pre("save", function(next) { const doc = this; console.log("doc in .pre: ", doc); // this should be the pre-save version of the doc, but it is the post-save version console.log("doc.history.length in model doc: ", doc.history.length); trigger.preSave(doc); next(); }) .post("save", function(doc) { trigger.postSave(doc); }) .post("update", function(doc) { trigger.postSave(doc); }); module.exports = mongoose.model("Customer", Schema); 操作的相关部分看起来像这样(我正在做的就是将新元素推入文档中称为“历史”的数组中):

save()

所以,我的问题是,如果在exports.updateHistory = async function(req, res) { let request = new CentralReqController( req, res, { // Allowed Parameters id: { type: String }, stageId: { type: String }, startedBy: { type: String } }, [ // Required Parameters "id", "stageId", "startedBy" ] ); let newHistoryObj = { stageId: request.parameters.stageId, startDate: new Date(), startedBy: request.parameters.startedBy, completed: false }; let customerToUpdate = await Customer.findOne({ _id: request.parameters.id }).exec(); let historyArray = await customerToUpdate.history; console.log("historyArray.length before push in update func: ", historyArray.length); historyArray.push(newHistoryObj); await customerToUpdate.save((err, doc) => { if (doc) console.log("history update saved..."); if (err) return request.sendError("Customer history update failed.", err); }); }; 发生之前应该触发pre操作上的save()钩子,为什么我要通过console.log查看文档显示已经对其执行过save()操作的文档?

1 个答案:

答案 0 :(得分:1)

您对pre / post“ save”挂钩的操作有些误解。用前/后挂钩术语来说,save是对数据库的实际保存操作。就是说,您在this钩中拥有的pre('save')是您在其上调用过.save()的对象,而不是数据库中的更新对象。例如:

let myCustomer = req.body.customer; // some customer object

// Update the customer object
myCustomer.name = 'Updated Name';

// Save the customer
myCustomer.save();

我们刚刚更新了客户名称。调用.save()时,它会触发钩子,如您上面所述。唯一的区别是,this钩中的pre('save')与myCustomer相同的对象,而不是数据库中的更新对象。相反,`post('save')钩子中的doc对象从数据库中 IS 更新了对象。

Schema.pre('save', function(next) {
  console.log(this); // Modified object (myCustomer), not from DB
)};

Schema.post('save', function(doc) {
  console.log(doc); // Modified object DIRECTLY from DB
});