You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB findOneAndUpdate返回Promise始终resolve的原因排查

问题原因

核心问题是你对findOneAndUpdate的返回结构判断完全错误:

  • 对MongoDB驱动来说,「没匹配到符合条件的文档」属于查询执行成功但无结果,不是执行错误,永远不会触发reject,只有数据库连接断了、语法写错这类底层故障才会进catch。你预期空库时方法执行失败,本身就是对方法行为的误解。
  • 该方法resolve的不是匹配到的文档本身,而是一个操作结果对象,结构类似:
{
  ok: 1, // 标记操作本身执行成功
  value: null, // 匹配到的文档,无匹配时为null
  lastErrorObject: {}
}

你代码里直接判断if (userDoc),这个结果对象永远是真值(哪怕value是null,对象本身转布尔也是true),所以不管有没有匹配到用户,永远会走resolve分支。

修复代码

首先修改User.activate方法,去掉多余的手动Promise包装(方法本身就返回Promise,手动包一层属于冗余写法,还容易漏捕获错误),正确判断返回结果里的文档字段:

User.activate = function(activationLink) {
    return usersCollection.findOneAndUpdate(
        { activationLink },
        { $set: { isActivated: true } },
        // 可选配置:返回更新后的文档,默认返回更新前的旧文档
        { returnDocument: 'after' }
    ).then(res => {
        if (res.value) {
            return 'Your account has been activated!'
        }
        throw new Error('This account does not exist!')
    })
}

controller层可以按需调整状态码,让响应更符合规范,核心逻辑不用大改:

exports.activate = function(req, res){
    User.activate(req.params.activationLink)
        .then(result => res.send(result))
        .catch(e => res.status(404).send(e.message))
}

路由层代码没有问题,不需要修改。

补充说明

如果用的是旧版Mongoose驱动,findOneAndUpdate默认会直接返回匹配到的文档(无匹配返回null),但如果开启了rawResult配置,也会返回上述原生驱动的结果对象,判断逻辑保持一致即可。

内容的提问来源于stack exchange,提问作者Andrey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 21:12:25