首页 > web前端 > js教程 > 正文

在 Mongoose 中实现用户添加好友功能

花韻仙語
发布: 2025-09-28 16:33:14
原创
933人浏览过

在 mongoose 中实现用户添加好友功能

本文旨在指导开发者如何在 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");
});
登录后复制

注意事项:

堆友
堆友

Alibaba Design打造的设计师全成长周期服务平台,旨在成为设计师的好朋友

堆友 306
查看详情 堆友
  • 事务: 在两个不同的集合中进行更改(更新 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");
  }
});
登录后复制

代码解释:

  1. 启动会话: const session = await mongoose.startSession(); 启动一个新的 Mongoose 会话。
  2. 开始事务: session.startTransaction(); 开始一个事务。
  3. 执行操作: 在 try 块中,执行所有数据库操作。关键是使用 .session(session) 将会话与每个操作关联起来。
  4. 提交事务: await session.commitTransaction(); 如果所有操作都成功,则提交事务,将所有更改保存到数据库。
  5. 中止事务: await session.abortTransaction(); 如果任何操作失败,则中止事务,回滚所有更改。
  6. 结束会话: session.endSession(); 结束会话。
  7. 错误处理: 在 catch 块中,处理错误并中止事务。

总结:

  • 为了确保数据一致性,建议使用事务。
  • 在用户模式中显式维护好友数组可能不是最佳做法。可以通过查询 FriendRequest 集合来获取好友列表。
  • 始终从已认证的用户信息中获取发送者 ID,以提高安全性。

通过以上步骤,你可以安全且有效地在 Mongoose 中实现用户添加好友的功能。记住,数据一致性和安全性是至关重要的,因此请务必使用事务并验证用户输入。

以上就是在 Mongoose 中实现用户添加好友功能的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号