为什么保存Mongoose模型时提示user.save is not a function错误
错误成因排查
- 核心原因:
User.findOne()是异步数据库操作方法,你没有添加await关键字等待查询完成,此时user变量实际存储的是Mongoose的Query查询对象,而非Mongoose文档实例,只有文档实例才携带save方法,Query对象没有该方法,调用就会抛出对应错误。 - 次要排查点:如果添加
await后仍报错,可检查如下场景:- 重置密码token无效或已过期,导致
findOne查询结果为null,对null调用save方法也会触发该错误 - 检查User模型的引入路径是否正确,是否成功引入了mongoose定义的模型实例
- 重置密码token无效或已过期,导致
修复代码示例
// 给异步操作添加await,确保拿到查询返回的文档实例 let user = await User.findOne({ resetPasswordToken: resetPasswordToken, resetPasswordExpire: { $gt: Date.now() }, }); // 增加空判断,避免查询结果为空时报错 if (!user) { return res.status(400).json({ errorMsg: "重置密码令牌无效或已过期" }); } // 更新字段 user.password = req.body.password; user.resetPasswordToken = undefined; user.resetPasswordExpire = undefined; // save操作也是异步,需要添加await等待执行完成 await user.save(); sendToken(user, 200, res);
额外注意点
你当前的用户Schema存在两处小问题,会影响功能稳定性:
password字段的必填属性误写为requires,正确应为required,否则密码必填校验会不生效pre('save')钩子中如果没有修改密码调用next()后,没有终止后续代码执行,可能会重复哈希密码,建议调整为:
userSchema.pre("save", async function (next) { if (!this.isModified("password")) { return next(); } this.password = await bcrypt.hash(this.password, 10); next(); });
内容的提问来源于stack exchange,提问作者Sefi R
相关产品推荐
相关产品推荐

