Reputation: 1638
I need to reuse one of pre middleware functions in another pre middleware, for that I extracted a function like so:
async function encryptPassword(next) {
if (!this.isModified('password')) {
return next();
}
this.password = await bcrypt.hash(this.password, 5);
this.passwordChangedAt = new Date();
next();
}
UserSchema.pre('save', encryptPassword);
UserSchema.pre("findOneAndUpdate", encryptPassword);
But I am getting an error saying that this.isModified
is not a function, I assume that this
is referring to something else. How to fix this?
Upvotes: 2
Views: 187
Reputation: 7103
I dived into these pre/post hooks with a help of debugger & docs and I have found several things (these apply to both pre
and post
):
Using save
hook will mean that this
refers a document itself. Thus, you can update its fields, call methods like isModified
, etc. You should not have any issues with the above method.
However, findOneAndUpdate
hook will mean that this
refers to a query instead of document. And Query object will not have documents or their inherited methods (like isModified
).
I checked with debugger and can confirm it is the case (up-to-date with documentation).
A list of hooks: https://mongoosejs.com/docs/middleware.html#types-of-middleware
You will see that only the following hooks allow to modify documents:
validate
save
remove
updateOne
deleteOne
init (note: init hooks are synchronous)
And all others will not. It seems this is intentional (https://github.com/Automattic/mongoose/issues/964).
To solve an issue with findOneAndUpdate
, it seems the only way (most closely resembling) is to rework to findOne
and updateOne
as separate queries.
Upvotes: 2