
本文旨在指导开发者如何在Mongoose中实现用户添加好友的功能,重点讲解在接受好友请求后如何正确更新User Schema中的好友数组。同时,文章也会探讨更高效的数据结构设计方案,以及在使用事务时需要注意的关键点,确保数据一致性。
首先,确保在处理好友请求时,发送者ID来自已验证的用户会话,而不是直接从前端表单获取。从前端获取用户ID存在安全风险,用户可以通过开发者工具篡改表单数据,冒充他人发送请求。
推荐的做法是从服务器端的会话或身份验证中间件中获取当前用户的ID。以下是修改后的前端表单和后端路由示例:
前端表单 (修改后):
<form action="/requests" method="POST"> <input type="hidden" name="receiver" value="<%= receiverUserId %>" /> <button type="submit">Send Friend Request</button> </form>
后端路由 (修改后):
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,将对方的 _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");
}
});注意事项:
直接修改两个不同的集合(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");
}
});关键点:
虽然在 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中的好友数组的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号