猫鼬 .findByIdAndUpdate 和更新前挂钩问题
Issue with mongoose .findByIdAndUpdate and pre-update hook
我有一个名为 UserSchema 的 mongoose-schema,它存储有关所有用户的信息。
我想让用户能够更改他的信息,我尝试使用 .findByIdAndUpdate。
这是相关代码:
router.post("/updateprofile", function(req,res,next) {
const {id, org, tel, email, firstName, lastName} = req.body;
Users.findByIdAndUpdate(id, {org : org, tel : tel, email : email, firstName : firstName , lastName : lastName}, function (err, response) {
if (err) throw err
res.json(response);
});
});
但是,在尝试更改信息时,我收到以下错误消息:Cannot read property 'password' of undefined
。我很确定这是由预更新挂钩引起的,但我无法删除它,因为我的 "forgot-password" 功能需要它。
这是代码:
UserSchema.pre('findOneAndUpdate', function (next) {
this.update({},{ $set: { password:
bcrypt.hashSync(this.getUpdate().$set.password, 10)}} )
next();
});
我很困惑为什么它仍然使用那个预挂钩,因为在挂钩中它正在寻找 findOneandUpdate
并且当我尝试更改我正在使用的数据时 findByIdAndUpdate
.
我尝试使用 .update()
代替,但这也不起作用。有谁知道我做错了什么以及如何解决它?
看起来 getUpdate 不是你想要的,试试这个:
UserSchema.pre('findOneAndUpdate', function (next) {
this._update.password = bcrypt.hashSync(this._update.password, 10)
next();
});
关于你的第二个问题,findByIdAndUpdate 是 findOneAndUpdate 的包装器。这是直接来自 Mongoose 源代码的代码供您参考
Model.findByIdAndUpdate = function(id, update, options, callback) {
if (callback) {
callback = this.$wrapCallback(callback);
}
if (arguments.length === 1) {
if (typeof id === 'function') {
var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
+ ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
+ ' ' + this.modelName + '.findByIdAndUpdate(id)\n'
+ ' ' + this.modelName + '.findByIdAndUpdate()\n';
throw new TypeError(msg);
}
return this.findOneAndUpdate({_id: id}, undefined);
}
代码中的注释为:
/**
* Issues a mongodb findAndModify update command by a document's _id field.
* `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
*
你可以在这里自己阅读源代码:https://github.com/Automattic/mongoose/blob/9ec32419fb38b74b240280aaba162f9ee4416674/lib/model.js
假设您计划将整个文档作为更新传递(例如使用 upsert: true
- 我认为这也在已接受的答案中假设)并且想要使用一个函数,这有效:
async function validation(next, self) {
// validation code here
}
YourSchema.pre('validate', async function(next) { validation(next, this) });
YourSchema.pre('findOneAndUpdate', async function(next) { validation(next, this._update) });
您只需将 this
替换为 this._update
即可告知函数它正在验证什么。
由于我无法访问 _update
属性,这对我有用:
UserSchema.pre('findOneAndUpdate', async function (this) {
let update = {...this.getUpdate()};
// Only run this function if password was modified
if (update.password){
// Hash the password
const salt = genSaltSync();
update.password = await hash(this.getUpdate().password, salt);
this.setUpdate(update);
}
})
我有一个名为 UserSchema 的 mongoose-schema,它存储有关所有用户的信息。 我想让用户能够更改他的信息,我尝试使用 .findByIdAndUpdate。 这是相关代码:
router.post("/updateprofile", function(req,res,next) {
const {id, org, tel, email, firstName, lastName} = req.body;
Users.findByIdAndUpdate(id, {org : org, tel : tel, email : email, firstName : firstName , lastName : lastName}, function (err, response) {
if (err) throw err
res.json(response);
});
});
但是,在尝试更改信息时,我收到以下错误消息:Cannot read property 'password' of undefined
。我很确定这是由预更新挂钩引起的,但我无法删除它,因为我的 "forgot-password" 功能需要它。
这是代码:
UserSchema.pre('findOneAndUpdate', function (next) {
this.update({},{ $set: { password:
bcrypt.hashSync(this.getUpdate().$set.password, 10)}} )
next();
});
我很困惑为什么它仍然使用那个预挂钩,因为在挂钩中它正在寻找 findOneandUpdate
并且当我尝试更改我正在使用的数据时 findByIdAndUpdate
.
我尝试使用 .update()
代替,但这也不起作用。有谁知道我做错了什么以及如何解决它?
看起来 getUpdate 不是你想要的,试试这个:
UserSchema.pre('findOneAndUpdate', function (next) {
this._update.password = bcrypt.hashSync(this._update.password, 10)
next();
});
关于你的第二个问题,findByIdAndUpdate 是 findOneAndUpdate 的包装器。这是直接来自 Mongoose 源代码的代码供您参考
Model.findByIdAndUpdate = function(id, update, options, callback) {
if (callback) {
callback = this.$wrapCallback(callback);
}
if (arguments.length === 1) {
if (typeof id === 'function') {
var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
+ ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
+ ' ' + this.modelName + '.findByIdAndUpdate(id)\n'
+ ' ' + this.modelName + '.findByIdAndUpdate()\n';
throw new TypeError(msg);
}
return this.findOneAndUpdate({_id: id}, undefined);
}
代码中的注释为:
/**
* Issues a mongodb findAndModify update command by a document's _id field.
* `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
*
你可以在这里自己阅读源代码:https://github.com/Automattic/mongoose/blob/9ec32419fb38b74b240280aaba162f9ee4416674/lib/model.js
假设您计划将整个文档作为更新传递(例如使用 upsert: true
- 我认为这也在已接受的答案中假设)并且想要使用一个函数,这有效:
async function validation(next, self) {
// validation code here
}
YourSchema.pre('validate', async function(next) { validation(next, this) });
YourSchema.pre('findOneAndUpdate', async function(next) { validation(next, this._update) });
您只需将 this
替换为 this._update
即可告知函数它正在验证什么。
由于我无法访问 _update
属性,这对我有用:
UserSchema.pre('findOneAndUpdate', async function (this) {
let update = {...this.getUpdate()};
// Only run this function if password was modified
if (update.password){
// Hash the password
const salt = genSaltSync();
update.password = await hash(this.getUpdate().password, salt);
this.setUpdate(update);
}
})