在设计多级评论系统时,查看了很多平台和别人的设计,基本是一样:
两级评论,第一级评论“文章”、“微博”等主题Topic,第二级评论这是回复reply,针对的主体时comment。reply无限次循环。
例如简书:
例如头条:
也有一种简单的灌贴逻辑。不在这里讨论。
设计思路
一级二级评论存放一张表,通过标记pid来区分。如果有需要提炼精选评论,可以额外扩展表结构。
客户端/前端获取评论内容时,先查询一级评论(分页提取),然后再查询多级回复。
【拒绝递归遍历多级评论】
表结构
CREATE TABLE `comment` (
`cid` int(11) unsigned NOT NULL AUTO_INCREMENT,
`tid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '帖子或文章ID,topic_id',
`uid` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '回复人的UID',
`replytime` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '回复时间戳',
`content` longtext NOT NULL COMMENT '回复内容',
`pid` int(11) DEFAULT NULL COMMENT '父节点评论,0为根节点',
`top_id` int(11) DEFAULT '0' COMMENT '一级评论ID,0为根节点',
PRIMARY KEY (`cid`),
KEY `uid` (`uid`),
KEY `tid` (`tid`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
数据展示
解释
pid : 找上级评论,二级及以下评论查询时非常有价值。
top_id : 记录一级评论信息。用于筛选一级和非一级,并且快速查询二级及以下评论的筛选条件。
示例
查询一篇文章(tid=3)的第一页评论信息。
# 一级评论
SELECT
*
FROM
`comment`
WHERE
tid = 3
AND pid = 0
ORDER BY
replytime DESC
limit 0, 10
# 二级及以下评论
SELECT
c.cid ,
c.uid ,
c.content ,
c.replytime ,
c.pid ,
c1.content AS p_content ,
c1.uid AS p_uid ,
c.top_id
FROM
`comment` AS c
LEFT JOIN `comment` AS c1 ON c.pid = c1.cid
WHERE
c.tid = 3 # 帖子/文章ID
AND c.top_id <> 0
AND c.top_id IN(5 , 6 , 7 , 9 , 12 , 17) # 一级评论的ID
ORDER BY
c.replytime
其他
1. 如果想要支持emoji表情,编码设置为utf8mb4,确保字段的编码格式。
2. id 根据需求可以设置为自增 或者 uuid,不过最好设置为uuid或者其他的全局唯一ID,后面会专门补充一篇全局唯一ID的Server设计。
3. 如果需要展示username信息,简单的可以联合user表。一级评论联合一次,二级评论需要联合两次。不过不建议这样设计。最好做数据冗余,把username放在comment表里(这里会衍生一个修改问题)。
4. 补充衍生的用户名修改问题,对有当前用户来说,除了自己的username,谁会关心和了解别人的username是否正确。所以当前用户浏览到自己的评论信息时,只要做更新就可以了。其他的不必要换成最新的。另一个解决方案是,username更新时,异步批量更新某一个时间范围内的就行(一般行业内不会这么做)。