参考链接:评论设计实现,完全模范bilibili实现评论功能,表的设计、sql如何查找,以及前端的一些设计_黄金贼贼的博客-CSDN博客
以上文章是使用一张表实现的。
废话不多说,直接讲解数据库设计。
核心思想
三张数据表,也即三级评论表实现,一级评论表存储评论对象下的评论,二级评论表存储一级评论的回复,三级评论表存储二级评论和其他三级评论的回复。
需要实现的需求:
1.评论列表查询:一级评论列表,一级评论对应的所有评论列表(不用树状结构展示,三级评论通过@方式展示);
2.查看对话:当三级评论回复二级评论时,三级评论旁会有“查看对话选项”,点击查看对话会展示该二级评论下所有的@回复(不仅仅是@该二级评论的,还包括@该二级评论下的其他三级评论的回复)。
数据库表
1.bilibili_user_comment_one_level 用户一级评论表
CREATE TABLE `bilibili_user_comment_one_level` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户一级评论ID',
`user_id` bigint(20) unsigned DEFAULT NULL COMMENT '用户ID',
`target_id` bigint(20) unsigned DEFAULT NULL COMMENT '目标ID',
`type` tinyint(4) DEFAULT NULL COMMENT '类型 1视频;2专栏;3番剧;4动态',
`like_num` int(11) DEFAULT '0' COMMENT '点赞数',
`reply_num` int(11) DEFAULT '0' COMMENT '回复数',
`dislike_num` int(11) DEFAULT '0' COMMENT '拉踩数',
`content` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '评论内容',
`comment_time` datetime DEFAULT NULL COMMENT '评论时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_taget_id` (`target_id`) USING BTREE,
KEY `idx_like_num` (`like_num`) USING BTREE,
KEY `idx_comment_time` (`comment_time`) USING BTREE,
KEY `idx_type` (`type`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户一级评论';
这张表很好看懂,就不做其他解释了。
2.bilibili_user_comment_two_level 用户二级评论表
CREATE TABLE `bilibili_user_comment_two_level` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户二级评论ID',
`user_id` bigint(20) unsigned DEFAULT NULL COMMENT '用户ID',
`target_id` bigint(20) unsigned DEFAULT NULL COMMENT '目标ID',
`one_comment_id` bigint(20) unsigned DEFAULT NULL COMMENT '一级评论ID',
`reply_user_id` bigint(20) unsigned DEFAULT NULL COMMENT '回复用户ID',
`type` tinyint(4) DEFAULT NULL COMMENT '类型 1视频;2专栏;3番剧;4动态',
`like_num` int(11) DEFAULT '0' COMMENT '点赞数',
`dislike_num` int(11) DEFAULT '0' COMMENT '拉踩数',
`content` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '评论内容',
`comment_time` datetime DEFAULT NULL COMMENT '评论时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_like_num` (`like_num`) USING BTREE,
KEY `idx_comment_time` (`comment_time`) USING BTREE,
KEY `idx_one_comment_id` (`one_comment_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户二级评论';
one_comment_id表示该二级评论对应回复的一级评论ID
3.bilibili_user_comment_three_level 用户三级评论表
CREATE TABLE `bilibili_user_comment_three_level` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户三级评论ID',
`user_id` bigint(20) unsigned DEFAULT NULL COMMENT '用户ID',
`target_id` bigint(20) unsigned DEFAULT NULL COMMENT '目标ID',
`one_comment_id` bigint(20) unsigned DEFAULT NULL COMMENT '一级评论ID',
`two_comment_id` bigint(20) unsigned DEFAULT NULL COMMENT '二级评论ID',
`reply_user_id` bigint(20) unsigned DEFAULT NULL COMMENT '回复用户ID',
`type` tinyint(4) DEFAULT NULL COMMENT '类型 1视频;2专栏;3番剧;4动态',
`like_num` int(11) DEFAULT '0' COMMENT '点赞数',
`dislike_num` int(11) DEFAULT '0' COMMENT '拉踩数',
`content` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '评论内容',
`comment_time` datetime DEFAULT NULL COMMENT '评论时间',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_comment_time` (`comment_time`) USING BTREE,
KEY `idx_one_comment_id` (`one_comment_id`) USING BTREE,
KEY `idx_two_comment_id` (`two_comment_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户三级评论';
one_comment_id表示该三级评论(除了一二级评论,其他都当作三级评论)对应回复的最上级也即一级评论ID。
two_comment_id表示该三级评论对应回复的次上级也即二级评论ID(不存储该三级评论回复的实际评论id,比如回复的是其他三级评论,该其他三级评论id并不存储,因为这对于我们所要实现的两个需求并没有什么用)
再说明:仅一级评论记录回复数,二三级评论不记录回复数,因为如果二三级评论也要记录回复数,那么如果是一个很深层次的评论回复,就需要层层向上找回复的评论并使其回复数+1,这样不太可取,b站好像也没有实现。
具体实现
1.评论列表查询
先根据target_id查询去一级评论表查询一级评论列表并分页,对每个一级评论,根据其id再去二级评论表和三级评论表(二三级评论都填充到一个集合中,这样才能实现不以树状形式展示)以one_comment_id = id为条件查询并分页。
对于三级评论记录,还要根据其reply_user_id回复用户ID字段去查询对应用户的昵称,前端展示时如果是三级评论就展示@[对应回复用户昵称],并展示“查看对话”选项。
2.三级评论查看对话
三级评论(二级以下评论)会展示“查看对话”选项,点击查看对话,取出该三级评论对应的二级评论id也即two_comment_id,去二级评论表中查询以id=two_comment_id为条件该评论信息,并去三级评论表中以two_comment_id=所给two_comment_id为条件查询该二级评论下的所有三级评论,也即该二级评论下的所有对话记录,并且三级评论还要填充@[回复用户昵称]。
【如果是三级评论就展示@[对应回复用户昵称],并展示“查看对话”选项】那么如何前端判断某评论是否是三级评论呢,可以取出其two_comment_id值,如果!=null就是三级评论,就展示@回复用户昵称和查看对话,当然也可以给哥级评论表添加个记录level,三级评论level=3,前端去除level判断是否为3即可。
最终
因为数据并没有填充,所以无法具体展示实现效果,非常抱歉,但是因为分了三张表,所以逻辑还是比较容易理解的 (应该没有什么逻辑漏洞吧,若我之后测试时遇到了bug再发篇文章进行改进)。