使用MERN Stack+Redux Toolkit开发社交APP时好友功能报错
问题分析与解决
核心错误原因
报错"User validation failed: password: Path password is required."的本质是:调用user.save()或friend.save()时,mongoose对User模型进行验证,发现当前文档对象中缺失password字段(该字段在Schema中被标记为必填)。
大概率是以下两种情况导致:
- User Schema中为
password字段设置了select: false(默认不返回该字段),查询用户时未显式指定获取password; - 查询用户时使用了
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
相关产品推荐
相关产品推荐

