一张表实现短视频“评论区“完整功能

前言

        现如今,不管是哪种类型的应用,评论区都少不了。从工具类的到媒体信息流类的,评论留言都是最基本的互动环节。比如抖音短视频下,针对视频每个用户都可以发表自己的观点;而针对用户的评论,其他的用户又可以对其进行评论,依次回复下去。

        那么,一个视频的评论回复的表如何设计?功能如何实现呢?如标题,这里是用一张表完成,但是在我完成功能后发现拆成两个张更合适(评论表和回复表),这个后面已经改了,最后也会说一下。

效果

        页面上展示是,视频下分页展示第一级的评论列表,评论下的评论是进行折叠,点击“查看全部”分页显示所有层级的评论。一张表的设计下,评论下的评论下……的评论是通过关联上一级主键的,也就是递归的方式。但是下面的是只要是对评论进行评论都放在第一级的评论下,而递归是树形结构。虽然也能通过对树形结构数据处理拉伸到二季下,但是在底下评论特别多的情况就会体验特别差。所以针对这个我对表格加了一个面包屑字段,表结构如下,然后再分次完成评论数据的如何添加,按页面方式查询的。

表结构

CREATE TABLE `short_video_comment` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `pid` int(11) DEFAULT '0' COMMENT '父级ID',
  `crumbs` json DEFAULT NULL COMMENT '面包屑',
  `video_id` int(11) DEFAULT '0',
  `user_id` int(11) DEFAULT '0',
  `commented_user_id` int(11) DEFAULT '0' COMMENT '被评论者用户ID',
  `is_pubisher` tinyint(1) DEFAULT '0' COMMENT '是否作者',
  `content` varchar(255) DEFAULT '' COMMENT '评论',
  `state` int(1) DEFAULT '1' COMMENT '1. 显示  0. 隐藏',
  `like_count` int(11) DEFAULT '0' COMMENT '点赞数',
  `create_time` int(11) DEFAULT '0' COMMENT '创建时间',
  `delete_time` int(11) DEFAULT '0' COMMENT '删除时间',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=282 DEFAULT CHARSET=utf8mb4 COMMENT='用户评论记录表';

 

如上图的 “crumbs” 字段是一个数组方式的json,也就是添加时会记录当前评论的关系链,从最顶层ID到最近的上一级。而实现分页显示第二级下的所有评论,只需要把 “crumbs” 索引为1的pid作为查询条件就能找到该id下的所有评论,如下是查询二级评论ID为285的所有评论列表。

select * from short_video_comment where json_extract(crumbs, "$[1]") = 285

        而对于关于crumbs如何存入和谁回复谁,就只需要在评论添加的时候,对上一级评论ID进行递归查询所有上级ID放入 "crumbs", 被回复者就更好办了,查询上一级评论的评论者ID(user_id),放入当前评论记录的 "commented_user_id",展示的时候只需要关联一下用户信息表就可以了,接下来就是业务代码演示了。

代码演示

▲评论添加
public static function commentAdd($videoInfo, $userId, $content, $commentInfo = [])
{
    $commentId = 0;
    $videoId = $videoInfo['id'] ?? 0;
    $publisherId = $videoInfo['user_id'] ?? 0;

    try {
        $crumbs = [0];
        if ($commentInfo) {
            $pid = $commentInfo['id'] ?? 0;
            $insert['commented_user_id'] = $commentInfo['user_id'] ?? 0;
            $insert['pid'] = $pid;
            $crumbs = ShortVideoComment::getCrumbs($pid);
        }

        $insert['video_id'] = $videoId;
        $insert['user_id'] = $userId;
        $insert['is_pubisher'] = $userId == $publisherId ? 1 : 0;
        $insert['content'] = $content;
        $insert['state'] = ShortVideoComment::STATE['SHOW'];
        $insert['create_time'] = time();
        $insert['crumbs'] = json_encode($crumbs);

        $commentId = ShortVideoComment::insertGetId($insert);

        if ($commentId && $videoId) {
            $map[] = ['id', '=', $videoId];
            ShortVideoModel::where($map)->setInc('comment_count');

            $userId && self::setRating(6, $userId, $videoId);
        }
    } catch (\Exception $e) {
        $preFileName = str::snake(__FUNCTION__);
        $path = self::getClassName();
        write_log("msg:" . $e->getMessage(), $preFileName . "_error", $path);
    }

    return $commentId;
}
▲获取面包屑
public static function getCrumbs($cateId = 0, &$ids = [])
{
    $idArr = array_merge((array)$cateId, $ids);
    $info = self::where('id', $cateId)->find();
    if ($info['pid'] != 0) {
        $idArr = self::getCrumbs($info['pid'], $idArr);
    } else {
        array_unshift($idArr, 0);
    }

    return $idArr;
}
▲数据查询
public static function getList($map, $page = 1, $size = 30, $pid = 0)
{
    $where[] = ['delete_time', '=', 0];
    $where[] = ['state', '=', self::STATE['SHOW']];
    $map = array_merge($where, $map);

    $field = ['id,crumbs,pid,video_id,user_id,commented_user_id,content'];
    $queryObj = self::field($field)
        ->with([
            'user' => function ($query) {
                $query->withField('id, nickname, avatar, mobile');
            },
            'commented_user' => function ($query) {
                $query->withField('id, nickname, avatar, mobile');
            }
        ])
        ->where($map);

    $pid && $queryObj->whereRaw("JSON_EXTRACT(`crumbs` ,'$[1]') = $pid");

    $list = $queryObj->page($page, $size)
        ->order('like_count desc')
        ->select();

    return $list;
}

写在最后

        以上是初版时候根据业务设计的表格,后来的评论区完全仿照某音,所以也就对表格进行了拆分。分成了评论表和回复表,只要是对评论进行评论就是回复,这样在后面数据庞大的时候,性能会更好一点。但是如何是前期设计的就是一张表,而迭代的时候也要有某音评论的效果,可以作为解决方法尝试滴。

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

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

相关文章

Spring Cloud—GateWay之限流

RequestRateLimiter RequestRateLimiter GatewayFilter 工厂使用 RateLimiter 实现来确定是否允许当前请求继续进行。如果不允许,就会返回 HTTP 429 - Too Many Requests(默认)的状态。 这个过滤器需要一个可选的 keyResolver 参数和特定于…

Spring @RequestMapping 工作原理

Spring RequestMapping 工作原理 配置基础启动类及Controller类 SpringBootApplication public class DemoServiceApplication {public static void main(String[] args) {SpringApplication.run(DemoServiceApplication.class, args);} }RestController public class HelloC…

单元测试用例到底该如何设计?

目录 前言 使用参数方法创建测试用例 使用执行路径方法创建测试用例 总结 前言 最近一些大公司在进行去测试化的操作,这一切的根源大概可以从几年前微软一刀切砍掉所有内部正式的测试人员开始说起,当时微软内部的测试工程师有一部分转职成了开发工程…

【数据结构常见七大排序(三)上】—交换排序篇【冒泡排序】And【快速排序】

目录 前言 1.冒泡排序 1.1冒泡排序动图 1.2冒泡排序源代码 1.3冒泡排序的特性总结 2.快速排序👑 2.1hoare版本实现思想 排序前 排序中 排序后 2.2hoare版本快排源代码 2.3分析先走 情况1🥇 情况2🥈 前言 交换类排序两个常见的排…

嵌入式工程师常用的软件工具推荐

前言:常言道:工欲善其事,必先利其器。作为一名合格的嵌入式工程师,日常可能需要接触和处理各种奇奇怪怪的问题,这时候一款高适配性的工具将会令工作效率大大提升。作者根据个人的实际使用情况与粉丝的客观感受&#xf…

紧跟国家“新能源+”模式!涂鸦智慧能源方案助力夏季用电节能提效

“今天的你是几分熟?” 今年夏天,高温来得比往年更早,五六月份就提前开启了滚滚热浪模式,京津冀和山东等地最高气温也一度突破了历史极值。在提前到来的高温“烤”验下,全社会供电能力面临着极大挑战。 中国电力网预…

完整的电商平台后端API开发总结

对于开发一个Web项目来说,无论是电商还是其他品类的项目,注册与登录模块都是必不可少的;注册登录功能也是我们在日常生活中最长接触的,对于这个业务场景的需求与逻辑大概是没有什么需要详细介绍的,市面上常见的邮箱注册…

PSP - Jackhmmer 搜索 EMBL 序列数据库的相似序列

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/131817060 EMBL (European Molecular Biology Laboratory,欧洲分子生物实验室):EMBL 数据库是一个由欧洲生物信息学研究所…

第六届字节跳动青训营报录比(宣传大使)

统计 前端基础卷:105 前端基础班:120-22(笔试不过基础班,宣传大使奖励进入)98 前端进阶卷:77 前端进阶班:18-216 后端基础卷:151 后端基础班:220 后端进阶卷:133 后端进…

LeetCode·每日一题·1851. 包含每个查询的最小区间·优先队列(小顶堆)

题目 示例 思路 离线查询: 输入的结果数组queries[]是无序的。如果我们按照输入的queries[]本身的顺序逐个查看,时间复杂度会比较高。 于是,我们将queries[]数组按照数值大小,由小到大逐个查询,这种方法称之为离线查询…

《微服务架构设计模式》第十二章 部署微服务应用

内容总结自《微服务架构设计模式》 部署微服务应用 一、部署模式分类二、编程语言特定的发布包格式1、概述2、利弊 三、将服务部署为虚拟机1、概览2、利弊 四、将服务部署为容器1、概述2、利弊3、K8S部署 五、Serverless部署1、概述2、利弊3、示例 六、总结 一、部署模式分类 …

视频融合平台EasyCVR级联后上级平台播放失败的问题排查与优化

EasyCVR视频融合平台基于云边端智能协同架构,具有强大的数据接入、处理及分发能力,平台可提供视频监控直播、云端录像、云存储、录像检索与回看、智能告警、平台级联、云台控制等视频能力与服务,可支持多协议、多类型的海量设备接入与分发。 …

7、PHP语法要点2

1、or 和 ||,&& 和 and 都是逻辑运算符,效果一样,但是其优先级却不一样。&&、||的优先级在赋值运算符之前,or和and在赋值运算符之后。 2、字符串变量及数组可以在echo输出时双引号内、双引号外均可引用&#xff…

Meta提出全新参数高效微调方案,仅需一个RNN,Transformer模型GPU使用量减少84%!

近来,随着ChatGPT和GPT-4模型的不断发展,国内外互联网大厂纷纷推出了自家的大语言模型,例如谷歌的PaLM系列,MetaAI的LLaMA系列,还有国内公司和高校推出的一些大模型,例如百度的文心一言,清华的C…

迅镭激光赋能工程机械,客户连续复购激光加工设备达双赢!

工程机械是装备制造业的重要组成部分,当前,我国已成为门类齐全、规模庞大、基础坚实、竞争力强的工程机械设备制造大国。 随着工程机械产业正在全面向智能化、绿色化转型,激光加工成为推动工程机械产业转型升级的重要工具,越来越多…

CS162 11-12 调度与死锁

调度 overview 1.FCFS 可以利用好cache缓存,减少上下文切换。 2.很直观,贪心,可以减少平均的响应时间 3 4. 5.等待调度的时间是平均的 6.优先级翻转,和优先级捐赠 解决 cfs中的调度 死锁 四个必要不充分条件 银行家算法&…

《深度学习推荐系统》笔记

目录 一、推荐系统是什么1.作用和意义2.推荐系统的架构2.1 逻辑架构2.2 技术架构 二、传统的推荐系统方法1. 协同过滤算法1.1 userCF&&ItemCF1.3 矩阵分解算法 2. 逻辑回归算法3. 因子分解机3.1 POLY2模型3.2 FM模型3.3 FFM模型3.4 小结 4. 组合模型4.1 GBDTLR组合模型…

数学建模-多元线性回归分析

回归分析介绍和分类 数据分类及数据的来源 线性回归 四种模型的解释、虚拟变量的设置以及交互项的解释 3个定量,7个定类插入,表格,包含标题,标题换黑色 可以右键,复制表格,excel中设置三线表 ,gen(A)是参数…

Linux 部署Vue+Spring Boot项目

部署Vue Spring Boot项目 安装redis wget http://download.redis.io/releases/redis-4.0.8.tar.gz tar -zxvf redis-4.0.8.tar.gz yum install gcc-c make make install如果出现下面的问题: yum install tcl make testredis-server myconifg/redis.conf输入客户端…

WordPress作为可扩展的企业级解决方案

网络商业世界就像一片汪洋大海,大型企业是大海中最大的鱼。然而,只因为你比其他人都大,并不意味着你不能逆流而上。相反,企业业务面临的挑战更大,对网站的技术要求更高。 多年来,大型公司通常依赖最昂贵的…
最新文章