​前言

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

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

效果

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

表结构

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;
}

写在最后

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

一张表实现类某音的视频"评论回复"功能的更多相关文章

  1. SpringSecurity结合数据库表实现权限认证

    SpringSecurity结合数据表实现权限认证: 下面的案例是在SpringBoot框架实现的: 步骤一:准备数据库表 以下是五张表的脚本 ### 用户表 create table Sys_Use ...

  2. bootstrap table 父子表实现【无限级】菜单管理功能

    bootstrap table 父子表实现[无限级]菜单管理功能 实现效果 前端代码 <%@ page language="java" import="java.u ...

  3. 图论——图的邻接表实现——Java语言(完整demo)

    1.图的简单实现方法——邻接矩阵 表示图的一种简单的方法是使用一个一维数组和一个二维数组,称为领接矩阵(adjacent matrix)表示法. 对于每条边(u,v),置A[u,v]等于true:否则 ...

  4. Mybatis 多表实现多对多查询、添加操作

    Mybatis 多表实现多对多查询.添加操作 学习内容: 1. 多对多之添加操作 1.1.需求 1.2.数据库表(多对多数据库设计需要设计中间表) 1.3.类设计 1.4.Mapper 接口和 Map ...

  5. Mybatis 多表实现多对一查询、添加操作

    Mybatis 多表实现多对一查询.添加操作 学习内容: 1. 多对一之添加操作 1.1.需求 1.2.数据库表(多对一或一对多,数据库外键都是设置在多的一方) 1.3.类设计 1.4.Mapper ...

  6. hibernate之关于使用连接表实现多对一关联映射

    [Hibernate]之关于使用连接表实现多对一关联映射 在我们项目使用中採用中间表最多的一般就是多对一,或者是多对多,当然一对一使用中间表也是能够的,可是这样的几率通常少之又少!所以这里重点介绍多对 ...

  7. DataStructure-链表实现指数非递减一元多项式的求和

    // 2-链表实现多项式的求和.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<stdio.h> #inclu ...

  8. 行逻辑链接的顺序表实现稀疏矩阵的相乘(Java语言描述)

    行逻辑链接,带行链接信息.程序有空指针BUG,至今未解决.还是C/C++适合描述算法数据结构.以后复杂的算法还是改用C/C++吧. 有BUG的代码,总有一天会换成没有BUG的. package 行逻辑 ...

  9. UI组件之AdapterView及其子类关系,Adapter接口及事实上现类关系

    AdapterView本身是一个抽象基类,它派生的的子类在使用方法上十分类似.AdapterView直接派生的三个子类:AbsListView.AbsSpinner,AdapterViewAnimat ...

  10. 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇

    一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...

随机推荐

  1. RESTful API 为何成为顶流 API 架构风格?

    作者孙毅,API7.ai 技术工程师,Apache APISIX Committer 万物互联的世界充满着各式各样的 API ,如何统筹规范 API 至关重要.RESTful API 是目前世界上最流 ...

  2. 【Azure Developer】Azure AD 注册应用的 OAuth 2.0 v2 终结点获取的 Token 解析出来依旧为v1.0, 这是什么情况!

    问题描述 使用 Azure AD 注册应用 Oauth2 v2.0的终结点(OAuth 2.0 token endpoint (v2):https://login.partner.microsofto ...

  3. 2022-11-10:写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率。 为了简单起见,你可以假设: words.txt只包括小写字母和 ‘ ‘ 。 每个单词只由小写

    2022-11-10:写一个 bash 脚本以统计一个文本文件 words.txt 中每个单词出现的频率. 为了简单起见,你可以假设: words.txt只包括小写字母和 ' ' . 每个单词只由小写 ...

  4. 2020-11-08:在Mysql中,三个字段A、B、C的联合索引,查询条件是B、A、C,会用到索引吗?

    福哥答案2020-11-08: 会走索引,原因是mysql优化器会把BAC优化成ABC. CREATE TABLE `t_testabc2` ( `id` int(11) NOT NULL AUTO_ ...

  5. golang调用sdl2,播放yuv视频

    golang调用sdl2,播放yuv视频 win10 x64下测试成功,其他操作系统下不保证成功. 采用的是syscall方式,不是cgo方式. 见地址 代码如下: package main impo ...

  6. 各类源码下载网址(u-boot,linux,openssl,文件系统)

    一.U-Boot源代码下载 1.U-Boot的官方网站: https://www.denx.de/wiki/U-Boot/http://ftp.denx.de/pub/u-boot/ftp://ftp ...

  7. 日增数据超10PB!揭秘沃尔玛Lakehouse架构选型之路

    沃尔玛系统产生了世界上最大和最多样化的数据集之一,每天数据增长超 10 PB. 来自许多不同的来源及其支持的后端系统,一系列大量的业务事件流被发送到主要由 Apache Kafka 支持的消息传递层. ...

  8. Django4全栈进阶之路8 createsuperuser创建超级管理员账号

    在 Django 4 中,可以使用 createsuperuser 命令来创建超级管理员账号.超级管理员拥有管理后台的所有权限,包括创建.编辑和删除用户.组.权限等操作. 下面是创建超级管理员账号的步 ...

  9. c++函数参数和返回值

    c++函数参数和返回值 函数存储位置 函数参数入栈顺序 初始化列表 函数的返回值 用参数引用来返回 返回一个参数指针 返回一个对象 总结 函数的几种变体 inline 函数 函数对象 lambda 函 ...

  10. 深入理解 python 虚拟机:魔术方法之数学计算

    深入理解 python 虚拟机:魔术方法之数学计算 在本篇文章当中主要给大家介绍在 python 当中一些常见的魔术方法,本篇文章主要是关于与数学计算相关的一些魔术方法,在很多科学计算的包当中都使用到 ...