我在我的网站(privacyfirstproducts.com)上有一个评论部分,我想在这个结构中显示评论(就像黑客新闻一样):
comment 1 (10 upvotes)
comment 4 (reply on comment 1, 7 upvotes)
comment 5 (reply on comment 1, 5 upvotes)
comment 8 (reply on comment 5, 8 upvotes)
...
comment 9 (reply on comment 1, 3 upvotes)
comment 3 (reply on comment 1, 0 upvotes)
comment 10 (reply on comment 1, 0 upvotes)
...
comment 6 (2 upvotes)
comment 7 (reply on comment 3, 2 upvotes)
comment 2 (0 upvotes)
...
我有这个postgresql
comments
-表:comment_id | original_id | upvotes | text | ...
------------------------------------------------------
1 | NULL | 10 | Hi.. | ...
2 | NULL | 0 | Je.. | ...
3 | 1 | 0 | Di.. | ...
4 | 1 | 7 | Si.. | ...
5 | 1 | 5 | Op.. | ...
6 | NULL | 2 | Op.. | ...
7 | 6 | 2 | Op.. | ...
8 | 5 | 8 | Op.. | ...
9 | 1 | 3 | Op.. | ...
10 | 1 | 0 | Th.. | ...
我想把这个作为postgresql的输出:
comment_id | original_id | upvotes | deep | text | ...
------------------------------------------------------
1 | NULL | 10 | 0 | Hi.. | ...
4 | 1 | 7 | 1 | Si.. | ...
5 | 1 | 5 | 1 | Op.. | ...
8 | 5 | 8 | 2 | Op.. | ...
9 | 1 | 3 | 1 | Op.. | ...
3 | 1 | 0 | 1 | Di.. | ...
10 | 1 | 0 | 1 | Th.. | ...
6 | NULL | 2 | 0 | Op.. | ...
7 | 6 | 2 | 1 | Op.. | ...
2 | NULL | 0 | 0 | Je.. | ...
我想这应该用递归来完成,但我不知道怎么做。
最佳答案
递归查询记录在手册的CTE部分。
首先选择根行(在您的示例中是顶级注释;在original_id IS NULL
中是注释)。
递归查询的第二部分(在下面示例中的UNION
之后)将子注释与已找到的子注释连接起来。它会自动重复,直到找不到更多的行为止。在您的情况下,第二个select需要在child.original_id = parent.comment_id
上将子注释连接到父注释。
查找每个节点的depth
很简单-在执行第二次选择时,只需将1添加到父行的深度。
更棘手的部分是获取所需的排序顺序(通过投票和ID,将注释按父级分组)。这可以通过累积投票和数组中每个注释的祖先id(以下示例中的path
列)来完成,然后按数组对行进行排序。请注意,示例中的投票计数已被否定,以便首先对较高的值进行排序。这可以通过排序DESC
来实现,但是当注释具有相同的投票数时,必须否定注释id才能首先对先前的注释进行排序。
WITH RECURSIVE comment_tree AS (
-- First select performed to get top level rows
SELECT
comment_id,
original_id,
upvotes,
text,
0 depth, -- depth in the tree
ARRAY[-upvotes, comment_id] path -- used to sort by vote then ID
FROM comment WHERE original_id IS NULL
UNION
-- Self referential select performed repeatedly until no more rows are found
SELECT
c.comment_id,
c.original_id,
c.upvotes,
c.text,
ct.depth + 1,
ct.path || ARRAY[-c.upvotes, c.comment_id]
FROM comment c
JOIN comment_tree ct ON c.original_id = ct.comment_id
)
SELECT * FROM comment_tree ORDER BY path;
关于javascript - 如何显示基于投票的递归评论?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53362825/