Mongoose中await不生效?更新文档返回旧属性问题排查
Mongoose更新操作await后返回旧文档的问题排查
问题重现
用户代码如下,在使用findOneAndUpdate和updateOne时,即使使用await,返回的文档或本地实例仍显示旧属性:
// 查询用户 const user = await User.findOne({ username, active: { $ne: false }, accessBanExpires: { $lt: Date.now() }, }).select('+password'); // 更新用户属性 let newuser; if (remember) { if (!user.rememberAcct) { newuser = await User.findOneAndUpdate(user._id, { rememberAcct: true, }, {returnDocument: 'after'}); console.log('check: ', user.rememberAcct); // 仍显示旧值 } } else if (user.rememberAcct) { await user.updateOne({ rememberAcct: false, }); } console.log(user.rememberAcct, newuser); // newuser返回旧属性,user实例也未更新
核心原因及解决方案
1. findOneAndUpdate返回旧文档的问题
- 选项参数需正确传递:确保
returnDocument: 'after'(Mongoose 6+版本推荐)或new: true(旧版本兼容)作为第三个参数传入。若参数结构错误,选项会被忽略,默认返回更新前的旧文档。 - 明确查询条件格式:建议将
user._id包装为对象{ _id: user._id }作为查询条件,避免潜在的参数解析异常。 - 检查中间件干扰:排查是否存在
pre('findOneAndUpdate')钩子,若钩子中修改了查询逻辑或返回值,可能导致返回旧文档。
修正后的findOneAndUpdate代码:
newuser = await User.findOneAndUpdate( { _id: user._id }, { rememberAcct: true }, { returnDocument: 'after' } // Mongoose 6+用此,旧版本可替换为 { new: true } );
2. 本地实例user未更新的问题
调用文档实例的updateOne方法时,仅会更新数据库中的数据,不会自动同步本地的user实例。因此console.log(user.rememberAcct)会一直显示旧值,需手动刷新实例:
await user.updateOne({ rememberAcct: false }); await user.reload(); // 从数据库重新加载最新数据到本地实例 console.log(user.rememberAcct); // 此时显示更新后的新值
额外注意点
- 若不需要保留本地实例,也可以直接用
User.findOne重新查询最新数据,替代reload操作。 - 确认Mongoose版本:6.x开始将
new选项替换为returnDocument,但仍兼容new: true写法。
内容的提问来源于stack exchange,提问作者Dr_Birkin
相关产品推荐
相关产品推荐

