我在MongoDB / Node后端中使用了pre
和post
钩子,以便比较文档的保存前和保存后版本,因此我可以通过基于发生了什么变化。在我的一个模型/集合中,这是有效的,但在另一个模型/集合中,它却没有按预期的方式工作,我不确定为什么。
在有问题的情况下,一些研究已经确定,即使我在使用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()
操作的文档?
答案 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
});