抖音评论系统的实现思路

                抖音大家都刷过。点开抖音的一个视频的评论,他会有一个根评论,根评论下面会有子评论,子评论中还有有对子评论的评论。具体如下图:

                                

        通过上面的图片可以直观的看见,这三种类型的评论。然后评论是根据时间的倒叙排列的。肯定还有会分页查询。用户点开评论,首先看到的是根评论。点开根评论,可以看见当前根评论对应的子评论。 大概的功能就是这些。

        一,需要实现的大致的功能点:

                1.根评论,及根评论下子评论的嵌套。

                2.评论用户基本信息的获取(用户图像,用户昵称)

                3.对子评论的评论的展现。(a用户回复b用户的子评论)

                4.用户的点赞,及点踩

                5.评论的展示顺序(根据时间顺序,还是评论的热度)

        二,数据库库表结构的设计:

        两张表,一张根评论表,一张子评论表。

建表语句如下:

CREATE TABLE sys_sub_comments (
    id INT AUTO_INCREMENT PRIMARY KEY COMMENT '评论的唯一标识符',  -- 主键 id,唯一标识每个评论
    userId INT NOT NULL COMMENT '评论者的用户 ID',               -- 评论者的用户 ID
    workId INT NOT NULL COMMENT '作品 ID(如视频或文章等)',      -- 作品 ID,指评论对应的作品
    content TEXT NOT NULL COMMENT '评论内容',                     -- 评论的内容
    targetUserId INT COMMENT '评论的目标用户 ID(如针对特定用户的评论)',  -- 评论的目标用户 ID
    parentCommentId INT DEFAULT NULL COMMENT '父评论 ID,用于层级关系,NULL 代表根评论',  -- 父评论 ID,用于表示评论的层级,NULL 代表没有父评论
    createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '评论的创建时间',  -- 评论的创建时间
    updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '评论的更新时间'  -- 评论的最后更新时间
) COMMENT = '评论表,存储用户对作品的评论信息,支持层级评论';


CREATE TABLE sys_comments (
    id INT AUTO_INCREMENT PRIMARY KEY COMMENT '评论的唯一标识符',  -- 主键 id,唯一标识每个评论
    userId INT NOT NULL COMMENT '评论者的用户 ID',               -- 评论者的用户 ID
    workId INT NOT NULL COMMENT '作品 ID(如视频或文章等)',      -- 作品 ID,指评论对应的作品
    content TEXT NOT NULL COMMENT '评论内容',                     -- 评论的内容
    createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '评论的创建时间',  -- 评论的创建时间
    updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '评论的更新时间'  -- 评论的最后更新时间
) COMMENT = '评论表,存储用户对作品的评论信息,支持层级评论';
        三,评论查询主要逻辑 

                1.根评论 查询逻辑

                        返回的vo对象结构:                               

	/**
	 * 根评论vo
	 *
	 */ 
 
/**
 * 商品根评论实体
 */
@Data
@NoArgsConstructor
public class CommentVO {
 
	Integer id;
 
	Integer goodsId;
 
	/**
	 * 评论用户信息
	 */
	UserSimpleVO userInfo;
  
	String content;
  
	String type;
 
	Timestamp createdAt;

}

        主要代码逻辑:

                首先根据作品id,分页查出当前页的评论:

SELECT * FROM sys_comments WHERE workId = 'root' ORDER BY create_time DESC LIMIT 20 OFFSET 1;

                根据userId获取当前页,所有评论用户的信息:

SELECT * FROM sys_user WHERE userId in (idList);

                主要代码如下:

//根据作品id,分页查询作品评论       
List<Comment> comments = commentService.selectByGoodsId(googsId,pageNumber,pageCount);
       if (ObjectUtils.isEmpty(comments)){
           return new ArrayList<>();
       }
        // 统计用户id,并进行去重
        List<Long> userIds = comments.stream().map(Commetn::getUserId)
                .distinct()
                .collect(Collectors.toList());
       //key是用户id,值是用户信息
       Map<Long, UserInfo> userInfos = userService.selectByIds(userIds);
        List<CommentVo> commentVos = new ArrayList<CommentVo>();
        //进行对应评论用户信息的填充
        for (Comment comment : comments) {
            CommentVo commentVo = new CommentVo();
            //进行原有属性的拷贝
            BeanUtils.copyProperties(comment,commentVo);
            //设置用户相关信息
            UserInfo userInfo = userInfos.get(comment.getUserId);
            commentVo.setUserInfo(userInfo);
            commentVos.add(commentVo);
        }
        return commentVos;

                2.子评论查询的主要逻辑

                        返回的vo对象结构: 相较于根评论,多了一个被评论者用户信息

/**
	 * 子评论vo
	 *
	 */ 
 
/**
 * 商品子评论实体
 */
@Data
@NoArgsConstructor
public class SubCommentVO extents CommentVO  {

    //被评论者用户信息
    private UserInfo targetUserInfo;
}

                主要代码逻辑:

                        根据父评论id筛选出,对应的子评论。 

SELECT * FROM sys_sub_comments WHERE parentCommentId= 'commentId' ORDER BY create_time DESC LIMIT 20 OFFSET 1;

                        根据用户id,获取对应的用户信息

SELECT * FROM sys_user WHERE userId in (idList);

                        代码逻辑:

//根据作品id,分页查询作品评论       
List<SubComment> subComments= SubCommentService.selectByParentCommetnId(parentCommetnId,pageNumber,pageCount);
       if (ObjectUtils.isEmpty(comments)){
           return new ArrayList<>();
       }
        // 统计用户id(包括评论用户id和被评论用户id)
        List<Long> userIds = SubComments.stream()
                ..flatMap(subComment -> Arrays.stream(new long[]{subComment.getUserId1(), subComment.getTargetUserId()}))
                .distinct()
                .collect(Collectors.toList());
       //key是用户id,值是用户信息
       Map<Long, UserInfo> userInfos = userService.selectByIds(userIds);
        List<CommentVo> subCommentVos = new ArrayList<CommentVo>();
        //进行对应评论用户信息的填充
        for (SubComment subComment : subComments) {
            SubCommentVo  = new SubCommentVo();
            //进行原有属性的拷贝
            BeanUtils.copyProperties(subComment ,subCommentVo);
            //设置用户相关信息
            UserInfo userInfo = userInfos.get(subComment.getUserId());
            subCommentVo.setUserInfo(userInfo);
            //设置目标评论者的用户信息
            UserInfo targetUserInfo = userInfos.get(subComment.getTargetUserInfo());
            subCommentVo.setTargetUserInfo(targetUserInfo);
            subCommentVos.add(subComment );
        }
        return subCommentVos;

                对于插入操作来说,都是常规操作,这里不做过多的说明。

        四,关于评论系统数据库的选择               

MySQL 和 MongoDB 都是流行的数据库系统,但它们在架构、使用场景和性能方面有显著的区别。

MySQL

优点

  • 关系型数据库:结构化数据,支持强大的 SQL 查询功能,适用于复杂的事务处理。
  • ACID 支持:确保数据的一致性、隔离性、持久性,适合需要严格事务管理的应用。
  • 成熟稳定:经过多年优化,社区支持广泛,文档和工具丰富。

缺点

  • 扩展性差:水平扩展复杂,处理大量并发和大规模数据时会遇到性能瓶颈。
  • 灵活性差:表结构必须事先定义,数据模式变化较为繁琐。

适用场景

  • 需要严格事务一致性和复杂查询的应用,如金融、电子商务、企业管理系统等。
MongoDB

优点

  • 文档型数据库:数据以 JSON 风格的 BSON 文档存储,灵活的模式设计,适合快速变化的应用。
  • 水平扩展:内建分片功能,支持横向扩展,适合大数据量和高并发场景。
  • 高性能:针对大量读写操作进行了优化,适合大规模应用。

缺点

  • 缺乏 ACID 支持:虽然 MongoDB 3.x 以后支持事务,但相比 MySQL,事务支持较弱。
  • 查询语言较弱:对于复杂查询,性能和表达能力不如 SQL,限制了某些类型的数据操作。

适用场景

  • 快速迭代的项目、实时数据分析、大数据处理、内容管理系统、物联网等。
总结:
  • MySQL:适合结构化数据,事务要求高的应用,如银行、电商系统等。
  • MongoDB:适合数据模式不固定,需求快速迭代和大数据量处理的应用,如日志记录、社交平台、大数据分析等。

        数据库的选择,根据平台的用户量,以及平台未来的增长量进行进行选择。

点点关注,点点赞呀,持续更新有用的知识............

                         

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/928767.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

4.STM32通信接口之SPI通信(含源码)---软件SPI与W25Q64存储模块通信实战《精讲》

经过研究SPI协议和W25Q64&#xff0c;逐步了解了SPI的通信过程&#xff0c;接下来&#xff0c;就要进行战场实战了&#xff01;跟进Whappy步伐&#xff01; 目标&#xff1a;主要实现基于软件的SPI的STM32对W25Q64存储写入和读取操作&#xff01; 开胃介绍&#xff08;代码基本…

PMP–一、二、三模、冲刺–分类–10.沟通管理

文章目录 技巧十、沟通管理 一模10.沟通管理--1.规划沟通管理--文化意识--军事背景和非军事背景人员有文化差异5、 [单选] 项目团队由前军事和非军事小组成员组成。没有军事背景的团队成员认为前军事团队成员在他们的项目方法中过于结构化和僵化。前军事成员认为其他团队成员更…

「Mac畅玩鸿蒙与硬件42」UI互动应用篇19 - 数字键盘应用

本篇将带你实现一个数字键盘应用&#xff0c;支持用户通过点击数字键输入数字并实时更新显示内容。我们将展示如何使用按钮组件和状态管理来实现一个简洁且实用的数字键盘。 关键词 UI互动应用数字键盘按钮组件状态管理用户交互 一、功能说明 数字键盘应用将实现以下功能&…

Svn如何切换删除账号

记录Svn清除切换账号 1.首先打开小乌龟的设置如下图 打开设置后单击已保存数据&#xff0c;然后选择清除 接上图选择清除后&#xff0c;就可以打勾选择清除已保存的账号&#xff0c;我们再次检出的就可以切换账号了 &#x1f449;总结 本次记录Svn清除切换账号 如能帮助到你…

7. 一分钟读懂“单例模式”

7.1 模式介绍 单例模式就像公司里的 打印机队列管理系统&#xff0c;无论有多少员工提交打印任务&#xff0c;大家的请求都汇总到唯一的打印管理中心&#xff0c;按顺序排队输出。这个中心必须全局唯一&#xff0c;避免多个队列出现资源冲突&#xff0c;保证打印任务井然有序。…

基于Transformer的编码器-解码器图像描述模型在AMD GPU上的应用

Transformer based Encoder-Decoder models for image-captioning on AMD GPUs — ROCm Blogs 图像描述&#xff0c;即基于生成式人工智能&#xff08;GenAI&#xff09;自动生成简洁的图像文本描述&#xff0c;在现实世界中有着非常重要的应用。例如&#xff0c;图像描述可以为…

Python爬虫——猫眼电影

用python中requests库爬取猫眼电影信息并保存到csv文件中 猫眼专业版 爬取界面 效果预览 代码 import requests import jsonurl1https://piaofang.maoyan.com/dashboard-ajax?orderType0&uuid1938bd58ddac8-02c2bbe3b009ed-4c657b58-144000-1938bd58ddac8&timeStamp…

非对称任意进制转换器(安卓)

除了正常进制转换&#xff0c;还可以输入、输出使用不同的数字符号&#xff0c;达成对数值进行加密的效果 点我下载APK安装包 使用unity开发。新建一个c#代码文件&#xff0c;把代码覆盖进去&#xff0c;再把代码文件添加给main camera即可。 using System.Collections; usin…

【HarmonyOS】鸿蒙应用地理位置获取,地理名称获取

【HarmonyOS】鸿蒙应用地理位置获取&#xff0c;地理名称获取 一、前言 首先要理解地理专有名词&#xff0c;当我们从系统获取地理位置&#xff0c;一般会拿到地理坐标&#xff0c;是一串数字&#xff0c;并不是地理位置名称。例如 116.2305&#xff0c;33.568。 这些数字坐…

OpenGL ES详解——文字渲染

目录 一、文字渲染 二、经典文字渲染&#xff1a;位图字体 1.概念 2.优缺点 三、现代文字渲染&#xff1a;FreeType 1.着色器 2.渲染一行文字 四、关于未来 一、文字渲染 当你在图形计算领域冒险到了一定阶段以后你可能会想使用OpenGL来绘制文字。然而&#xff0c;可能…

C++设计模式之外观模式

动机 下图中左边方案的问题在于组件的客户和组件中各种复杂的子系统有了过多的耦合&#xff0c;随着外部客户程序和各子系统的演化&#xff0c;这种过多的耦合面临很多变化的挑战。 如何简化外部客户程序和系统间的交互接口&#xff1f;如何将外部客户程序的演化和内部子系统…

【Redis篇】 List 列表

在 Redis 中&#xff0c;List 是一种非常常见的数据类型&#xff0c;用于表示一个有序的字符串集合。与传统的链表结构类似&#xff0c;Redis 的 List 支持在两端进行高效的插入和删除操作&#xff0c;因此非常适合实现队列&#xff08;Queue&#xff09;和栈&#xff08;Stack…

RE逆向基础知识及常见题型

通用寄存器 FAX: &#xff08;针对操作数和结果数据的&#xff09;累加器EBX: &#xff08;DS段的数据指针&#xff09;基址寄存器ECX: &#xff08;字符串和循环操作的&#xff09;计数器EDX: &#xff08;I/O指针&#xff09;数据寄存器ESI: &#xff08;字符串操作源指针&a…

APM装机教程(四):山鹰H743飞控四旋翼装机

文章目录 前言一、飞控说明书二、接线三、参数设置四、电机接线和转向 前言 固件版本&#xff1a;Copter 4.5.7 地面站&#xff1a;QGC 遥控器&#xff1a;云卓T10 飞控&#xff1a;山鹰H743 GPS&#xff1a;微空M9 这个飞控的原理图是开源的&#xff0c;网盘链接&#xff1a;…

实验四:MyBatis 的关联映射

目录&#xff1a; 一 、实验目的&#xff1a; 熟练掌握实体之间的各种映射关系。 二 、预习要求&#xff1a; 预习数据库原理中所讲过的一对一、一对多和多对多关系 三、实验内容&#xff1a; 1. 查询所有订单信息&#xff0c;关联查询下单用户信息(注意&#xff1a;因为一…

【C#设计模式(17)——迭代器模式(Iterator Pattern)】

前言 迭代器模式可以使用统一的接口来遍历不同类型的集合对象&#xff0c;而不需要关心其内部的具体实现。 代码 //迭代器接口 public interface Iterator {bool HashNext();object Next(); } //集合接口 public interface Collection {Iterator CreateIterator(); } //元素迭…

MySQL 主从同步一致性详解

MySQL主从同步是一种数据复制技术&#xff0c;它允许数据从一个数据库服务器&#xff08;主服务器&#xff09;自动同步到一个或多个数据库服务器&#xff08;从服务器&#xff09;。这种技术主要用于实现读写分离、提升数据库性能、容灾恢复以及数据冗余备份等目的。下面将详细…

Redis4——持久化与集群

Redis4——持久化与集群 本文讲述了1.redis在内存占用达到限制后的key值淘汰策略&#xff1b;2.redis主从复制原理&#xff1b;3.redis的哨兵模式&#xff1b;4.redis集群模式。 1. 淘汰策略 设置过期时间 expire key <timeout>只能对主hash表中的键设置过期时间。 查…

矩阵转置        ‌‍‎‏

矩阵转置 C语言代码C 语言代码Java语言代码Python语言代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 输入一个n行m列的矩阵A&#xff0c;输出它的转置 A T A^T AT。 输入 第一行包含两个整数n和m&#xff0c;表示矩阵A的行数和列数。…

Linux 无界面模式下使用 selenium

文章目录 前言什么是无界面模式&#xff1f;具体步骤安装谷歌浏览器查看安装的谷歌浏览器的版本下载对应版本驱动并安装Python 测试代码 总结个人简介 前言 在 Linux 服务器上运行自动化测试或网页爬虫时&#xff0c;常常需要使用 Selenium 来驱动浏览器进行操作。然而&#x…