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

如何在findOneAndUpdate中检测用户名不存在时插入并执行后续逻辑

如何在findOneAndUpdate中处理不存在的用户名并执行相同失败登录流程?

最有效的实现方式是利用MongoDB findOneAndUpdate 的upsert: true选项,这样可以用一次原子操作完成"更新已有用户"或"插入新用户",不需要额外的查询和插入步骤,既高效又能避免并发问题。

你的尝试里手动插入再递归调用的方式会增加数据库操作次数,还可能带来并发风险,而开启upsert是更简洁可靠的方案。下面是修改后的完整代码:

function _lockIfFailedAttemptsReachLimit(username, req, res, next) {
  colUser.findOneAndUpdate(
    { username }, 
    {
      // 设置失败登录时间
      $set: { failedLoginAt: new Date() },
      // 递增失败次数(插入时会自动初始化为1)
      $inc: { nFailedLogin: 1 },
      // 可选:插入新用户时设置默认字段,比如账户锁定状态默认未锁定
      $setOnInsert: { isLocked: false }
    }, 
    { 
      upsert: true, // 开启upsert:找不到匹配文档则插入新文档
      returnOriginal: false 
    }, 
    (err, result) => {
      if (err) {
        next('Undefined error!');
        return;
      }

      // 不管是更新还是插入,result.value都会返回对应的文档
      let foundUser = result.value;
      let nFailed = _.get(foundUser, 'nFailedLogin', 0);
      let errMsg = `Invalid username or password. You have tried ${nFailed}/${MAX_FAILED_LOGIN_ATTEMPTS} login attempts`;

      if (nFailed < MAX_FAILED_LOGIN_ATTEMPTS) {
        next(errMsg);
      } else {
        _lockAccount(username, (err, lockResult) => {
          if (!err) {
            errMsg += `. Your account has been locked for ${WAITING_TIME_AFTER_LOCKED} seconds.`;
          }
          next(errMsg);
        });
      }
    }
  );
}

关键修改说明:

  1. 开启upsert: true:这是核心改动,MongoDB会自动判断用户名是否存在——存在则执行更新逻辑,不存在则插入新文档,全程是原子操作,不会出现中间状态。
  2. $inc的自动初始化特性:当插入新文档时,$inc: { nFailedLogin: 1 }会自动把nFailedLogin设为1,正好对应第一次失败尝试的场景,完全符合你的需求。
  3. 可选的$setOnInsert:如果新插入的用户需要一些默认字段(比如账户锁定状态isLocked默认false),可以用$setOnInsert指定,这些字段只会在插入新文档时生效,更新已有文档时不会被修改。
  4. 修正代码失误:你原来在找不到用户时获取客户端IP作为username插入,这应该是个错误,我们直接使用传入的username参数,确保插入的是尝试登录的目标用户名。

流程逻辑:

  • 无论用户名是否存在,一次findOneAndUpdate操作就能完成失败登录记录的更新/初始化。
  • 后续的失败次数判断、账户锁定逻辑和原来完全一致,不需要额外调整。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:49:41