0

0

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

花韻仙語

花韻仙語

发布时间:2025-09-28 16:33:14

|

943人浏览过

|

来源于php中文网

原创

在 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");
});

注意事项:

I-Shop购物系统
I-Shop购物系统

部分功能简介:商品收藏夹功能热门商品最新商品分级价格功能自选风格打印结算页面内部短信箱商品评论增加上一商品,下一商品功能增强商家提示功能友情链接用户在线统计用户来访统计用户来访信息用户积分功能广告设置用户组分类邮件系统后台实现更新用户数据系统图片设置模板管理CSS风格管理申诉内容过滤功能用户注册过滤特征字符IP库管理及来访限制及管理压缩,恢复,备份数据库功能上传文件管理商品类别管理商品添加/修改/

下载
  • 事务: 在两个不同的集合中进行更改(更新 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 中实现用户添加好友的功能。记住,数据一致性和安全性是至关重要的,因此请务必使用事务并验证用户输入。

相关专题

更多
什么是中间件
什么是中间件

中间件是一种软件组件,充当不兼容组件之间的桥梁,提供额外服务,例如集成异构系统、提供常用服务、提高应用程序性能,以及简化应用程序开发。想了解更多中间件的相关内容,可以阅读本专题下面的文章。

178

2024.05.11

Golang 中间件开发与微服务架构
Golang 中间件开发与微服务架构

本专题系统讲解 Golang 在微服务架构中的中间件开发,包括日志处理、限流与熔断、认证与授权、服务监控、API 网关设计等常见中间件功能的实现。通过实战项目,帮助开发者理解如何使用 Go 编写高效、可扩展的中间件组件,并在微服务环境中进行灵活部署与管理。

213

2025.12.18

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

308

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

740

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

88

2025.08.19

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

524

2023.09.20

数据库三范式
数据库三范式

数据库三范式是一种设计规范,用于规范化关系型数据库中的数据结构,它通过消除冗余数据、提高数据库性能和数据一致性,提供了一种有效的数据库设计方法。本专题提供数据库三范式相关的文章、下载和课程。

350

2023.06.29

如何删除数据库
如何删除数据库

删除数据库是指在MySQL中完全移除一个数据库及其所包含的所有数据和结构,作用包括:1、释放存储空间;2、确保数据的安全性;3、提高数据库的整体性能,加速查询和操作的执行速度。尽管删除数据库具有一些好处,但在执行任何删除操作之前,务必谨慎操作,并备份重要的数据。删除数据库将永久性地删除所有相关数据和结构,无法回滚。

2075

2023.08.14

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Node.js 教程
Node.js 教程

共57课时 | 8.9万人学习

CSS3 教程
CSS3 教程

共18课时 | 4.7万人学习

Vue 教程
Vue 教程

共42课时 | 6.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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