按赞成票对 LTree 排序

Sort LTree by Upvotes

我正在写一个评论系统。我已经能够按照这里的教程获得层次结构 (http://www.postgresonline.com/journal/archives/173-Using-LTree-to-Represent-and-Query-Hierarchy-and-Tree-Structures.html)

    SELECT n.node_path          AS PATH,
           n.note_id            AS _1,
           n.note_no            AS _2,
           n.public_key         AS _3,
           n.upvotes            AS _4
    FROM public.comment_table AS n
             INNER JOIN public.comment_table AS a ON (a.node_path @> n.node_path)
    GROUP BY _1, PATH
    ORDER BY PATH

但是,我无法通过投票对行进行排序。我不能在这里简单地 ORDER BY PATH, n.upvotes 因为在同一个线程上的回复会有不同的 node pathsnode_paths 是使用 public_key.

计算的

从例子中给出

a (0 upvotes)
-> b (0 upvotes)
-> c (1 upvote)
d (1 upvote)
-> e (0 upvotes)

bc 的节点路径将分别为 a.ba.c。我不能简单地从节点路径和 ORDER BY 中减去 bc。如果我这样做,结果会是这个顺序:

a
d
-> b
-> c
-> e

这是有道理的,因为如果您从 node_path 中删除每一行的 public_key,它只会按最短的 node_path 到最长的排序。

我如何编写查询以生成正确的层次结构并按赞成票排序,如下所示:

d (1)
-> e (0)
a (0)
-> c (1)
-> b (0)

假设赞成票数不断变化,并且您选择了 ltree 路线来避免递归,我想不出一个不需要递归的解决方案,因为每一行都需要访问对其祖先的计数进行投票,以找到将自己置于结果中的位置。

with recursive base as (
  select node_path, upvotes, 
         array[row_number() over (order by upvotes desc, node_path)] as sort_path
    from comment_table 
   where nlevel(node_path) = 1
  union all
  select c.node_path, c.upvotes, 
         p.sort_path||row_number() over (order by c.upvotes desc, c.node_path)
    from base p
    join comment_table c 
      on subpath(c.node_path, 0, -1) = p.node_path
)
select * from base order by sort_path;

 node_path | upvotes | sort_path 
-----------+---------+-----------
 d         |       1 | {1}
 d.e       |       0 | {1,3}
 a         |       0 | {2}
 a.c       |       1 | {2,1}
 a.b       |       0 | {2,2}
(5 rows)