
本文旨在指导开发者如何在Mongoose中实现用户添加好友的功能,重点讲解在接受好友请求后如何正确更新User Schema中的好友数组。同时,文章也会探讨更高效的数据结构设计方案,以及在使用事务时需要注意的关键点,确保数据一致性。
安全地处理好友请求
首先,确保在处理好友请求时,发送者ID来自已验证的用户会话,而不是直接从前端表单获取。从前端获取用户ID存在安全风险,用户可以通过开发者工具篡改表单数据,冒充他人发送请求。
推荐的做法是从服务器端的会话或身份验证中间件中获取当前用户的ID。以下是修改后的前端表单和后端路由示例:
前端表单 (修改后):
<input type="hidden" name="receiver" value="" />
后端路由 (修改后):
router.post("/requests", (req, res) => { const { receiver } = req.body; FriendRequest.create({ sender: req.user._id, // 从已验证的用户会话中获取 sender ID receiver, }) .then(() => { res.status(204).send(); }) .catch((error) => { res.status(500).send("Error sending friend request"); });});
在这个修改后的代码中,req.user._id 代表当前已验证用户的ID,你需要根据你使用的身份验证中间件来调整获取用户ID的方式。
更新User Schema中的好友数组
当用户接受好友请求时,需要更新双方的 User Schema,将对方的 _id 添加到各自的 friends 数组中。以下是更新 User Schema 的代码示例:
router.post("/requests/:id/accept", async (req, res) => { try { const request = await FriendRequest.findById(req.params.id); request.status = "accepted"; await request.save(); const currentUserId = req.user._id; // 获取当前用户ID const currentUser = await User.findById(currentUserId); const otherUser = await User.findById(request.sender); currentUser.friends.push(request.receiver); otherUser.friends.push(currentUserId); await currentUser.save(); await otherUser.save(); res.redirect("/requests"); } catch (error) { console.error("Error accepting friend request:", error); res.status(500).send("Error accepting friend request"); }});
注意事项:
在更新 friends 数组之前,请确保 request.receiver 和 currentUserId 都是有效的 ObjectId 类型。在生产环境中,需要添加错误处理机制,以便在发生错误时能够及时发现并处理。
使用事务保证数据一致性
直接修改两个不同的集合(FriendRequest 和 User)可能导致数据不一致。例如,如果服务器在更新 FriendRequest 集合后崩溃,但尚未更新 User 集合,则会导致数据不一致。为了解决这个问题,可以使用 Mongoose 的事务功能。
以下是使用事务的代码示例:
const mongoose = require('mongoose');router.post("/requests/:id/accept", async (req, res) => { const session = await mongoose.startSession(); session.startTransaction(); try { const request = await FriendRequest.findById(req.params.id).session(session); request.status = "accepted"; await request.save({ session }); const currentUserId = req.user._id; // 获取当前用户ID const currentUser = await User.findById(currentUserId).session(session); const otherUser = await User.findById(request.sender).session(session); currentUser.friends.push(request.receiver); otherUser.friends.push(currentUserId); await currentUser.save({ session }); await otherUser.save({ session }); await session.commitTransaction(); session.endSession(); res.redirect("/requests"); } catch (error) { await session.abortTransaction(); session.endSession(); console.error("Error accepting friend request:", error); res.status(500).send("Error accepting friend request"); }});
关键点:
mongoose.startSession() 创建一个新的会话。session.startTransaction() 启动一个事务。在查询和保存文档时,使用 .session(session) 将操作与事务关联。session.commitTransaction() 提交事务,所有操作都将永久保存到数据库。session.abortTransaction() 回滚事务,所有操作都将撤销。session.endSession() 结束会话。
更高效的数据结构设计
虽然在 User Schema 中维护一个 friends 数组是常见的做法,但它可能不是最有效的方法,尤其是在用户拥有大量好友的情况下。
另一种更高效的方法是只维护 FriendRequest 集合,并通过查询来获取好友列表。例如:
FriendRequest.find({ $or: [ { sender: req.user._id, status: "accepted" }, { receiver: req.user._id, status: "accepted" }, ],}) .populate("sender receiver") // 可选:填充用户数据 .then((friendRequests) => { const friends = friendRequests.map((request) => { return request.sender._id.equals(req.user._id) ? request.receiver : request.sender; }); console.log(friends); }) .catch((e) => { // handle error });
这种方法的优点是不需要在多个集合中维护数据,从而避免了数据不一致的问题。缺点是每次获取好友列表都需要执行查询。
总结
在 Mongoose 中实现好友关系需要仔细考虑数据一致性和性能。使用事务可以确保数据一致性,但会增加代码的复杂性。选择合适的数据结构取决于具体的应用场景和性能要求。在开发过程中,请始终关注安全性,并避免从前端获取敏感数据。
以上就是在Mongoose中实现好友关系:更新User Schema中的好友数组的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1524220.html
微信扫一扫
支付宝扫一扫