我在我的网站(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)
...

我有这个postgresqlcomments-表:
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/

10-13 08:59