Postgres如何代表行ID的树?

时间:2018-08-13 12:10:49

标签: sql postgresql

我想在Postgres 10数据库中表示文件和文件夹的层次结构。像

这样的结构
Photos/
  |-- Dog.jpg
  |-- Cat.jpg
  |-- Places/
         |-- Paris.jpg
         |-- Berlin.jpg
Songs/
  |-- Happy.mp3

将被表示为类似

| id | filename   | parent_id |
|----|------------|-----------|
| 1  | Photos     | null      |
| 2  | Songs      | null      |
| 3  | Cat.jpg    | 1         |
| 4  | Happy.mp3  | 2         |
| 5  | Places     | 1         |
| 6  | Berlin.jpg | 5         |
| 7  | Dog.jpg    | 1         |
| 8  | Paris.jpg  | 5         |

数据库将跟踪多个用户,并且每个用户将具有自己的文件文件夹层次结构。

我一直在阅读Postgres的ltree扩展名,似乎可以解决我的问题,但是我不知道它是否是它,并且很难测试。标签看起来像是任意字符串-是否可以告诉Postgres标签应该是同一表中的ID字段?我是否需要为每个用户创建一个初始根节点,仅让他们将子节点附加到该子节点上,或者发出一个该子节点的子节点,然后发出一个select * from nodes where path >@那个根节点,您可以通过这种方式选择后代吗?

还是当我应该查看其他类型的数据库时,我是在强迫Postgres做一些从未打算做的事情吗?

1 个答案:

答案 0 :(得分:1)

正确回答:这取决于您的用例。

如果树是非常静态的(子节点变化不是很频繁),那么ltree是一个很好的选择。您可以对子节点和排序进行非常快速和舒适的查询。在那种情况下,我会为您提到的每个用户做一个根引用。

另一方面:在ltree中移动子树可能会迫使您大量重写ltree数据结构。例如。如果您有一棵像1.1.1、1.1.2和1.2.1这样的树,并且想要在根之后的第一级中更改子树的顺序,那么这三个值都必须更改其数据。

因此,如果您的树结构非常动态,那么我将尝试上述结构:将父节点保存在邻接列表(可能还有排序索引)中,并使用递归CTE查询进行查询

https://www.postgresql.org/docs/current/static/queries-with.html

http://schinckel.net/2014/09/13/long-live-adjacency-lists/

最后但并非最不重要的一点是,您可以使用“嵌套集”结构(https://en.wikipedia.org/wiki/Nested_set_model)进行尝试。

每种方法都有其自身的优点和缺点。您必须进行非常详细的分析,也许还要创建一些原型来测试哪种原型最适合您。

进一步阅读:

https://medium.com/notes-from-a-messy-desk/representing-trees-in-postgresql-cbcdae419022

https://explainextended.com/2009/09/24/adjacency-list-vs-nested-sets-postgresql/