评论系统设计实践

大前提:
我把评论和回复看作是不一样的两种内容,分别对待,如无特别说明,评论就是指直接针对主题的,回复是针对评论的

需要解决的问题:

1.每次拉列表都要去查评论(包含评论和回复)总数和每条评论下的总回复数

不同的设计方案

1.将评论表和回复表分开设计

评论表:

CREATE TABLE `mt_comments` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '评论唯一ID',
  `topic_id` bigint(20) NOT NULL COMMENT '被评论的主题的唯一ID',
  `topic_type` int(4) NOT NULL COMMENT '被评论的主题的类型ID',
  `content` text NOT NULL COMMENT '评论的内容',
  `from_uid` bigint(20) NOT NULL COMMENT '评论者UID',
  `gmt_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '评论创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

是针对主题的评论,所以不需要存储to_uid字段

回复表:

CREATE TABLE `mt_comment_replies` (
  `id` int(11) NOT NULL COMMENT '回复唯一ID',
  `topic_id` bigint(20) NOT NULL,
  `topic_type` int(4) NOT NULL,
  `comment_id` bigint(20) NOT NULL COMMENT '被回复的评论的唯一ID',
  `content` text NOT NULL COMMENT '回复的内容',
  `from_uid` bigint(20) NOT NULL COMMENT '进行回复动作的用户的UID',
  `to_uid` bigint(20) NOT NULL COMMENT '被回复的用户UID',
  `reply_id` bigint(20) NOT NULL COMMENT '如果reply_type是评论类型,就是comment_id; 如果reply_type是回复类型,就是被回复的回复的唯一ID',
  `reply_type` tinyint(4) NOT NULL COMMENT '回复的类型有两种,一种是对评论的回复,另一种是对回复的回复',
  `gmt_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '回复创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

1.回复表我添加了一个comment_id字段来表示该回复挂在的根评论id,这样设计也是出于性能方面的考虑,我们可以直接通过评论id一次性的捞出该评论下的所有回复,然后通过程序来编排回复的显示结构。通过适当的冗余来提高性能也是常用的优化手段之一

2.因为是将回复单独分了一张表,如果需要获取评论总数,需要将评论表和回复表中对应一个topic的数量加在一起才是总评论数,两张表都增加了topic_id和topic_type,这样查询一个topic的回复总数就不用拿到评论表的id再去查回复表的回复总数了

2.单表设计

前提:
除了评论,所有的回复都是第二级,不做叠楼的操作
CREATE TABLE `mt_comments_tmp` (
  `id` binary(20) NOT NULL COMMENT '评论ID',
  `comment_id` bigint(20) NOT NULL COMMENT '一级评论ID,该ID只会是评论的ID,不是回复的ID',
  `reply_id` bigint(20) NOT NULL COMMENT '该条内容的父级内容的ID,内容可以是评论,也可以是回复,如果是评论该值是0,如果是回复,该值是本条内容的父级的评论或回复的ID',
  `topic_id` bigint(20) NOT NULL COMMENT '主题唯一ID',
  `topic_type` tinyint(4) NOT NULL COMMENT '主题类型ID',
  `content` text NOT NULL COMMENT '评论或者回复的内容',
  `from_uid` bigint(20) NOT NULL COMMENT '发送内容的用户UID',
  `to_uid` bigint(20) NOT NULL COMMENT '被回复的用户的UID',
  `gmt_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

特别字段说明:
1.id,一条记录就是一条发表的内容,可做hash
2.comment_id,一级评论ID,该ID只会是评论的ID,不是回复的ID,方便拉取某一条评论下面的所有回复
3.reply_id,该条内容的父级内容的ID,内容可以是评论,也可以是回复,如果是评论该值是0,如果是回复,该值是本条内容的父级的评论或回复的ID,方便查询针对某一个回复下的所有回复

如果是叠楼的方式,如何实现

待完善。。。

使用mysql的注意小事项:

mysql的字段unsigned属性不方便移植,所以我不使用
utf8mb4不只兼容utf8,还能比utf8能展示更新的字符,将编码改为utf8mb4外不需要做其他转换。评论内容字段使用utf8mb4 charset。表被设置之后,表中的字段会默认沿用表的字符集

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值