
本文旨在指导开发者如何在 Mongoose 中实现用户添加好友的功能,并探讨了维护用户好友关系的不同策略。重点介绍如何安全地处理好友请求,以及在用户接受好友请求后,如何正确更新用户模式中的好友数组。同时,也讨论了使用额外数组存储好友关系的必要性,并提出了更优的查询方案。
安全地处理好友请求
在处理好友请求时,安全性至关重要。不要从前端获取发送者 ID,因为这容易受到篡改。应该从已经认证的用户信息中获取发送者 ID。假设你已经创建了一个用于检查认证的中间件,可以这样修改 POST 请求处理程序:
router.post("/requests", (req, res) => { const { receiver } = req.body; // 创建一个新的 FriendRequest 实例 const newRequest = new FriendRequest({ sender: req.user._id, // 从认证用户获取 sender ID receiver, }); // 将好友请求保存到数据库 newRequest .save() .then(() => { // 重定向到成功页面或发送成功响应 res.status(204).send(); }) .catch((error) => { // 适当处理错误 res.status(500).send("Error sending friend request"); }); });
更简洁的做法是使用 FriendRequest.create() 方法:
FriendRequest.create({ sender: req.user._id, receiver }) .then(() => { // 重定向到成功页面或发送成功响应 res.status(204).send(); }) .catch((error) => { // 适当处理错误 res.status(500).send("Error sending friend request"); });
更新用户模式中的好友数组 (可选,但不推荐)
虽然可以在用户模式中显式地维护一个好友数组,但这并非总是必要的。如果需要获取好友列表,可以通过查询 FriendRequest 集合来实现。
FriendRequest .find({sender: req.user._id, status: 'accepted'}) .then((listOfFriends)=>{ console.log(listOfFriends); }) .catch((e)=>{ // 处理错误 })
如果仍然希望在用户模式中显式地维护一个好友数组,则需要在接受好友请求时更新该数组:
router.post("/requests/:id/accept", async (req, res) => { 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); currentUser.friends.push(request.receiver); await currentUser.save(); const otherUser = await User.findById(request.receiver); otherUser.friends.push(currentUserId); await otherUser.save(); res.redirect("/requests"); });
注意事项:
- 事务: 在两个不同的集合中进行更改(更新 FriendRequest 和 User)可能导致数据不一致。例如,如果服务器在更新 FriendRequest 后崩溃,但 User 未更新,则数据库将处于不一致状态。为了确保数据一致性,应该使用事务。
使用事务确保数据一致性
为了确保数据一致性,需要使用事务。Mongoose 支持事务,可以使用 startSession() 方法启动一个会话,并在该会话中执行多个操作。如果在会话中的任何操作失败,则可以回滚所有操作。
以下是如何使用事务更新 FriendRequest 和 User 集合的示例:
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); currentUser.friends.push(request.receiver); await currentUser.save({ session }); const otherUser = await User.findById(request.receiver).session(session); otherUser.friends.push(currentUserId); await otherUser.save({ session }); await session.commitTransaction(); session.endSession(); res.redirect("/requests"); } catch (error) { await session.abortTransaction(); session.endSession(); console.error("Transaction failed:", error); res.status(500).send("Error accepting friend request"); } });
代码解释:
- 启动会话: const session = await mongoose.startSession(); 启动一个新的 Mongoose 会话。
- 开始事务: session.startTransaction(); 开始一个事务。
- 执行操作: 在 try 块中,执行所有数据库操作。关键是使用 .session(session) 将会话与每个操作关联起来。
- 提交事务: await session.commitTransaction(); 如果所有操作都成功,则提交事务,将所有更改保存到数据库。
- 中止事务: await session.abortTransaction(); 如果任何操作失败,则中止事务,回滚所有更改。
- 结束会话: session.endSession(); 结束会话。
- 错误处理: 在 catch 块中,处理错误并中止事务。
总结:
- 为了确保数据一致性,建议使用事务。
- 在用户模式中显式维护好友数组可能不是最佳做法。可以通过查询 FriendRequest 集合来获取好友列表。
- 始终从已认证的用户信息中获取发送者 ID,以提高安全性。
通过以上步骤,你可以安全且有效地在 Mongoose 中实现用户添加好友的功能。记住,数据一致性和安全性是至关重要的,因此请务必使用事务并验证用户输入。
以上就是在 Mon前端 go session ai red 中间件 Session try catch const 数据库


