我想在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做一些从未打算做的事情吗?
答案 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/