一张表实现类某音的视频"评论回复"功能
前言
现如今,不管是哪种类型的应用,评论区都少不了。从工具类的到媒体信息流类的,评论留言都是最基本的互动环节。比如抖音短视频下,针对视频每个用户都可以发表自己的观点;而针对用户的评论,其他的用户又可以对其进行评论,依次回复下去。
那么,一个视频的评论回复的表如何设计?功能如何实现呢?如标题,这里是用一张表完成,但是在我完成功能后发现拆成两个张更合适(评论表和回复表),这个后面已经改了,最后也会说一下。

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

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

一张表实现类某音的视频"评论回复"功能的更多相关文章
- SpringSecurity结合数据库表实现权限认证
SpringSecurity结合数据表实现权限认证: 下面的案例是在SpringBoot框架实现的: 步骤一:准备数据库表 以下是五张表的脚本 ### 用户表 create table Sys_Use ...
- bootstrap table 父子表实现【无限级】菜单管理功能
bootstrap table 父子表实现[无限级]菜单管理功能 实现效果 前端代码 <%@ page language="java" import="java.u ...
- 图论——图的邻接表实现——Java语言(完整demo)
1.图的简单实现方法——邻接矩阵 表示图的一种简单的方法是使用一个一维数组和一个二维数组,称为领接矩阵(adjacent matrix)表示法. 对于每条边(u,v),置A[u,v]等于true:否则 ...
- Mybatis 多表实现多对多查询、添加操作
Mybatis 多表实现多对多查询.添加操作 学习内容: 1. 多对多之添加操作 1.1.需求 1.2.数据库表(多对多数据库设计需要设计中间表) 1.3.类设计 1.4.Mapper 接口和 Map ...
- Mybatis 多表实现多对一查询、添加操作
Mybatis 多表实现多对一查询.添加操作 学习内容: 1. 多对一之添加操作 1.1.需求 1.2.数据库表(多对一或一对多,数据库外键都是设置在多的一方) 1.3.类设计 1.4.Mapper ...
- hibernate之关于使用连接表实现多对一关联映射
[Hibernate]之关于使用连接表实现多对一关联映射 在我们项目使用中採用中间表最多的一般就是多对一,或者是多对多,当然一对一使用中间表也是能够的,可是这样的几率通常少之又少!所以这里重点介绍多对 ...
- DataStructure-链表实现指数非递减一元多项式的求和
// 2-链表实现多项式的求和.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include<stdio.h> #inclu ...
- 行逻辑链接的顺序表实现稀疏矩阵的相乘(Java语言描述)
行逻辑链接,带行链接信息.程序有空指针BUG,至今未解决.还是C/C++适合描述算法数据结构.以后复杂的算法还是改用C/C++吧. 有BUG的代码,总有一天会换成没有BUG的. package 行逻辑 ...
- UI组件之AdapterView及其子类关系,Adapter接口及事实上现类关系
AdapterView本身是一个抽象基类,它派生的的子类在使用方法上十分类似.AdapterView直接派生的三个子类:AbsListView.AbsSpinner,AdapterViewAnimat ...
- 一步步实现windows版ijkplayer系列文章之二——Ijkplayer播放器源码分析之音视频输出——视频篇
一步步实现windows版ijkplayer系列文章之一--Windows10平台编译ffmpeg 4.0.2,生成ffplay 一步步实现windows版ijkplayer系列文章之二--Ijkpl ...
随机推荐
- 两分钟操作完成用VScode连接MySQL查询数据
第一步:下载一个插件,MySQL Syntax 安装后要是重启或刷新后没有出现 再安装一个MySQL 第二步:下载vscode-database 第三步:把需要的插件下载好后,接下来就开始操作 输入 ...
- MapStruct实体映射转换
1.MapStruct简介 MapStruct是一个代码生成器,它基于约定优于配置的方法,极大地简化了Java bean类型之间映射的实现.生成的映射代码使用简单的方法调用,快速.类型安全且易于理解. ...
- CS144 计算机网络 Lab2:TCP Receiver
前言 Lab1 中我们使用双端队列实现了字节流重组器,可以将无序到达的数据重组为有序的字节流.Lab2 将在此基础上实现 TCP Receiver,在收到报文段之后将数据写入重组器中,并回复发送方. ...
- 【FAQ】关于JavaScript版本的华为地图服务Map的点击事件与Marker的点击事件存在冲突的解决方案
一. 问题描述 创建地图对象,并添加marker标记,对map和marker均添加了点击事件: <body> <script> function initMap() { // ...
- js对象方法大全
JavaScript中Object构造函数的方法 Object构造函数的方法节 Object.assign() 通过复制一个或多个对象来创建一个新的对象. Object.create() 使用指定的原 ...
- 2020-09-07:Docker的四种网络类型?
福哥答案2020-09-07: 敲docker network ps命令,显示三种模式.1.bridge模式:使用–net =bridge指定,默认设置.桥接式网络模式(默认).容器的默认网络模式,d ...
- 1406, "Data too long for column 'od_seq' at row 1"
问题描述:1406, "Data too long for column 'od_seq' at row 1" 问题分析:录入数据长度超出字段的最大限制 解决方法:增加max_le ...
- 2022年第十四届四川省大学生程序设计大赛 A
A Adjacent Swapping 题意: 给定一个字符串,每次可以移动相邻字符,求最小移动次数可以把它变成s+s这样左右两边相同的字符串. 思路: 1:我们知道他一定是偶数长度,所以我们把字符串 ...
- Ubuntu22.04 安装单机版kubernetes
前言 上期讲到要实现.net 6框架下的EF Core操作数据库基本增删改查,没有及时兑现.没有兑现的原因就是因为安装kubernetes.安装kubernetes的过程是灾难性的,也是十分顺利的.灾 ...
- LeetCode 周赛 347(2023/05/28)二维空间上的 LIS 最长递增子序列问题
本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 提问. 往期回顾:LeetCode 单周赛第 346 场 · 仅 68 人 AK 的最短路问题 周赛 347 概览 ...