公司接了一个小项目,项目里的多级评论有些技巧,值得写一篇文章记录。

需求是帖子下的评论,先看下设计图:

网上调研了一番,结合当前业务情况,发现一张评论表就够了。

评论表:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
CREATE TABLE `xm_comment` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `customer_id` int(11) NOT NULL DEFAULT '0' COMMENT '用户id',
  `nickname` varchar(64) NOT NULL DEFAULT '' COMMENT '用户昵称',
  `content` varchar(256) NOT NULL DEFAULT '' COMMENT '评论内容',
  `post_id` int(11) NOT NULL DEFAULT '0' COMMENT '帖子id',
  `root_id` int(11) NOT NULL DEFAULT '0' COMMENT '二级评论所属一级评论id',
  `reply_id` int(11) NOT NULL DEFAULT '0' COMMENT '回复评论id',
  `reply_customer_id` int(11) NOT NULL DEFAULT '0' COMMENT '回复用户id',
  `reply_nickname` varchar(64) NOT NULL DEFAULT '' COMMENT '回复用户昵称',
  `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '评论类型 1-一级评论 2-二级评论',
  `create_time` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间',
  `update_time` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
  `is_del` tinyint(4) NOT NULL DEFAULT '0' COMMENT '是否删除 1-是 0-否',
  PRIMARY KEY (`id`),
  KEY `idx_postId_type_rootId` (`post_id`,`type`,`root_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评论';

表中的customer_id、nickname是一级评论用户信息,reply_customer_id、reply_nickname是二级评论用户信息,由于用户昵称是 “用户”+手机尾号后四位,可以认为不会修改,所以直接存评论表。如果是可能修改的昵称,可以根据用户id批量获取昵称,放到redis。

root_id是二级评论所属一级评论id,后面的两个主要sql语句会用到,主要为了拉取一级评论下的所有二级评论(二级评论不需要分页)

reply_id是所回复的评论id,记录当前这条记录是评论哪条评论

type用于区分一级评论、二级评论。

主要逻辑是先拉一级评论,再根据一级评论id获取二级评论

1
2
3
1select * from xm_comment where post_id = ? and type = 1 and is_del = 0 order by create_time desc limit ?, ?

2select * from xm_comment where post_id = ? and type = 2 and root_id in (?) and is_del = 0 order by create_time desc

service层主要代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
for _, comm := range commentList {
		subComments := make([]*httpapi.SubComment, 0, len(subCommentList))
		for _, subComm := range subCommentList {
			// 只保留每个一级评论下的二级评论
			if comm.Id != subComm.RootId {
				continue
			}

			subComments = append(subComments, &httpapi.SubComment{
				Id:              subComm.Id,
				CustomerId:      subComm.CustomerId,
				Nickname:        subComm.Nickname,
				Content:         subComm.Content,
				PostId:          subComm.PostId,
				RootId:          subComm.RootId,
				ReplyId:         subComm.ReplyId,
				ReplyCustomerId: subComm.ReplyCustomerId,
				ReplyNickname:   subComm.ReplyNickname,
				Type:            subComm.Type,
				CreateTime:      subComm.CreateTime,
			})
		}

		commentResults = append(commentResults, &httpapi.Comment{
			Id:             comm.Id,
			CustomerId:     comm.CustomerId,
			Nickname:       comm.Nickname,
			Content:        comm.Content,
			PostId:         comm.PostId,
			Type:           comm.Type,
			CreateTime:     comm.CreateTime,
			SubCommentList: subComments,
		})
	}

项目是一个公司的官网论坛,预估数据量不多,评论这块没有用redis