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

使用MERN Stack+Redux Toolkit开发社交APP时好友功能报错

问题分析与解决

核心错误原因

报错"User validation failed: password: Path password is required."的本质是:调用user.save()或friend.save()时,mongoose对User模型进行验证,发现当前文档对象中缺失password字段(该字段在Schema中被标记为必填)。

大概率是以下两种情况导致:

  1. User Schema中为password字段设置了select: false(默认不返回该字段),查询用户时未显式指定获取password;
  2. 查询用户时使用了select('-password')排除该字段,导致文档对象中无password,触发必填验证失败。

另外代码存在逻辑bug:

friend.friends = friend.friends.filter((id) => id !== id);

参数id与外层的当前用户ID重名,导致判断条件id !== id永远为true,会清空好友列表而非移除指定好友ID。

解决方案

方案1:显式获取password字段(推荐,保留验证完整性)

查询用户时显式包含password字段,同时修复好友移除逻辑:

export const addRemoveFriend = async (req, res) => {
  try {
    const { id, friendId } = req.params;
    // 显式获取password字段
    const user = await User.findById(id).select('+password');
    const friend = await User.findById(friendId).select('+password');

    if (user.friends.includes(friendId)) {
      user.friends = user.friends.filter((friend) => friend !== friendId);
      // 更换参数名避免重名冲突
      friend.friends = friend.friends.filter((userId) => userId !== id);
    } else {
      user.friends.push(friendId);
      friend.friends.push(id);
    }
    await user.save();
    await friend.save();

    const friends = await Promise.all(
      user.friends.map((id) => User.findById(id))
    );
    const formattedFriends = friends.map(
      ({ _id, firstName, lastName, username, avatarPath }) => {
        return { _id, firstName, lastName, username, avatarPath };
      }
    );

    res.status(200).json(formattedFriends);
  } catch (err) {
    res.status(404).json({ error: err.message });
  }
};

方案2:使用findByIdAndUpdate修改(更高效,避免全字段验证)

直接通过MongoDB更新操作修改好友列表,无需查询完整文档再save,不会触发模型全字段验证:

export const addRemoveFriend = async (req, res) => {
  try {
    const { id, friendId } = req.params;
    const user = await User.findById(id);

    if (user.friends.includes(friendId)) {
      // 移除好友
      await User.findByIdAndUpdate(id, { $pull: { friends: friendId } });
      await User.findByIdAndUpdate(friendId, { $pull: { friends: id } });
    } else {
      // 添加好友
      await User.findByIdAndUpdate(id, { $push: { friends: friendId } });
      await User.findByIdAndUpdate(friendId, { $push: { friends: id } });
    }

    // 重新查询格式化后的好友列表
    const updatedUser = await User.findById(id);
    const friends = await Promise.all(
      updatedUser.friends.map((friendId) => User.findById(friendId))
    );
    const formattedFriends = friends.map(
      ({ _id, firstName, lastName, username, avatarPath }) => ({
        _id, firstName, lastName, username, avatarPath
      })
    );

    res.status(200).json(formattedFriends);
  } catch (err) {
    res.status(404).json({ error: err.message });
  }
};

方案3:跳过save时的验证(不推荐,可能绕过其他必填字段检查)

若确定仅修改好友列表,可在save时跳过验证,同时修复逻辑bug:

// 修改后保存时跳过验证
await user.save({ validateBeforeSave: false });
await friend.save({ validateBeforeSave: false });

内容的提问来源于stack exchange,提问作者M7md-Dev

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 09:04:55