在PHP/MySQL中实现递归评论

4
我正在尝试编写一个评论系统,人们可以在其他评论上进行评论,并且这些评论会作为递归线程显示在页面上。(Reddit的评论系统是我想要实现的一个例子),但我不知道如何实现这样一个系统,而不会非常缓慢和计算成本高。
我想象每个评论都会存储在一个评论表中,并包含一个parent_id,它将是另一个评论的外键。我的问题在于如何获取所有这些数据而不需要大量查询,然后如何有效地组织评论以符合其所属的顺序。有人有任何关于如何最好实现这一点的想法吗?
7个回答

5
尝试使用嵌套集模型。在《在MySQL中管理分层数据》一文中有详细描述。(链接)该模型的主要好处是不需要使用递归来检索子节点,查询也相当简单。缺点是插入和删除需要更多的工作。此外,它的扩展性非常好。我知道一个使用这种方法存储讨论层次结构的极大系统。

1

我通常使用父子系统进行工作。

例如,考虑以下内容:

表comment( commentID, pageID, userID, comment [, parentID] )

parentID是一个外键,指向同一表中的commentID,它是可选的(可以为NULL)。

要选择评论,请使用此方法来获取“根”评论:

SELECT * FROM comments WHERE pageID=:pageid AND parentID IS NULL

还有这个是给孩子的:

SELECT * FROM comments WHERE pageID=:pageid AND parentID=:parentid

但是如果孩子们有孩子,他们又有孩子,或者有很多评论怎么办?这种方法似乎会涉及到大量的查询,并且当存在大量评论时可能会变得非常缓慢。 - GSto

1

1

我不得不实现递归评论。 我在嵌套模型中遇到了困难,让我解释一下:

假设您想要文章的评论。 我们称根评论为直接附加到此文章的评论。 我们称回复评论为对另一个评论的答案。

我注意到(不幸的是),我希望根评论按日期降序排列, 但我希望回复评论按日期升序排列!! 矛盾!

因此,嵌套模型并没有帮助我减少查询次数。

这是我的解决方案:

创建具有以下字段的评论表:

id
article_id
parent_id(可为空)
date_creation
email
whateverYouLike
sequence
depth

此实现的3个关键字段是parent_id、sequence和depth。 parent_id和depth有助于插入新节点。

Sequence是真正的关键字段,它是一种嵌套模型仿真。

每次插入新的根评论时,它是x的倍数。 我选择x=1000,这基本上意味着我最多可以有1000个嵌套评论(这是我发现的唯一缺点 对于此系统,但此限制可以轻松修改,现在对我的需求已足够)。

最近的根评论必须是具有最大序列号的评论。

现在回复评论:我们有两种情况:回复根评论或回复回复评论。

在这两种情况下,算法都是相同的: 使用父级序列号,检索一个以获取您的序列号。 然后,您必须更新在父级序列号下方且在基本序列号上方的序列号, 基本序列号是所涉及的根评论正下方的根评论的序列号。

我不希望你完全理解这一切,因为我不是一个很好的解释者, 但我希望它可以给你新的想法。 (至少对我来说比嵌套模型更有效=请求较少,这才是真正的目标)。


1

这里有另一个网站提供了关于该方法的信息和一些源代码。


1

这只是一个建议,但由于我现在也面临同样的问题, 如何在评论表中添加一个序列字段(int)和一个深度字段,并在插入新评论时进行更新。

序列字段将用于对评论进行排序。 深度字段将指示评论的递归级别。

然后,难点就是在用户插入新评论时进行正确的更新。

我还不知道实现起来有多难, 但我相信一旦实现,我们将比基于嵌套模型的解决方案获得更好的性能提升。


0

我采取了简单的方法。

  • 保存根 ID(如果是评论,则为 post_id)
  • 保存父 ID

然后使用 post_id 获取所有评论,并在客户端上递归排序。 我不在乎是否有 1000 条评论。 这发生在内存中。

这是一个数据库调用,那就是昂贵的一部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接