头图

我的博客的评论功能的实现,在之前的几篇文章中也有总结:

我在设计数据表时,是把所有的评论和回复都放在了同一张表中,之所以这么设计,主要是考虑到:

  1. 博客的数据量比较小,一张表就够了;
  2. 查询某文章下的评论时,查一次,就可以把所有评论和回复都查出来;

sql 语句:

SELECT c1.*, c2.nick as reply_nick, c2.face as reply_face
FROM comments c1
LEFT JOIN comments c2 ON c1.replyid = c2.id
WHERE c1.aid=?

查询出文章 id 下的所有评论,并且把回复的评论也查出来。若该评论的回复 id replyid 正好是某评论的 id,说明该评论是回复的某条评论,则把回复的评论的昵称、头像等数据也查出来。

但这种 SQL 语句的存在一个严重的问题:无法分页

假设每页的数据是 20 条,若我设置的 limit 为 20,其实查出来的是「评论+回复」一共 20 条,然后再形成楼中楼的结构后,当前页就不足 20 条数据了;而且还可能存在某条评论中的回复数据不全的问题。

那么该如何解决呢?

1. 查询出所有数据

就像上面的 sql 语句,把某文章里的所有评论数据都查出来,拼装成楼中楼的结构。要么后端根据页码分页后返回给前端;要么把所有数据返回给前端,前端自己进行分页。

其实在数据量不大的时候,这种做法没有问题,但是当数据量比较大的时候,每次都查询所有数据,然后再组装所有数据。速度肯定会逐渐慢下来。

2. 两次查询

既然「评论+回复」无法准确分页,那我们可以分成两次查询:

  1. 按照分页条数,查询出评论数据;
  2. 查询这些评论的所有回复的数据,这里不再分页;

大概的 SQL 语句如下:

# 查询评论数据,即replyid为null的数据
SELECT * FROM comments WHERE aid=? AND replyid IS NULL LIMIT ?, ?

再查询所有的回复数据:

# 将上面查到的所有评论的id给到当前语句
SELECT * FROM comments WHERE aid=? AND replyid IN (1,2,3)

然后将评论和回复的数据进行拼装。

3. 分成两张表

我们之前是把评论和回复放在一张表中。这里我们可以把评论数据和回复数据分别放到两张表里。类似于第 2 节中的两次查询,只不过这里查询的不同的数据表而已。

我的博客地址:评论回复在一张表里的评论系统如何进行分页


小蚊酱
5.3k 声望205 粉丝

爱生活,爱前端