文件系统中目录的分层/树数据库

JOH*_*OHN 32 sql sqlite tree path hierarchical-data

我想将存在于磁盘上的目录存储到数据库中,同时保持其层次结构/树结构.

这是一个无花果,

                         (ROOT)
                       /        \ 
                    Dir2        Dir3
                   /    \           \
                 Dir4   Dir5        Dir6
                 /          
               Dir7

我正在使用SQLite数据库.

  • 请建议我在SQLite数据库中存储上述结构的sql查询.

  • 和一个查询,以便在我选择一个目录时检索目录的完整路径.

即假设我选择Dir6然后我会得到像ROOT/Dir2/dir3/dir7这样的完整路径

Mik*_*ike 39

这是SQLite的快速闭包表示例.我没有包含将项目插入现有树的语句.相反,我刚刚手动创建了语句.您可以在模型中找到分层数据幻灯片中的插入和删除语句.

为了我在插入目录的ID时的理智,我重命名了目录以匹配他们的ID:

        (ROOT)
      /        \ 
    Dir2        Dir3
    /    \           \
  Dir4   Dir5        Dir6
  /          
Dir7
Run Code Online (Sandbox Code Playgroud)

创建表格

CREATE TABLE `filesystem` (
  `id` INTEGER,
  `dirname` TEXT,
  PRIMARY KEY (`id`)
);

CREATE TABLE `tree_path` (
  `ancestor` INTEGER,
  `descendant` INTEGER,
  PRIMARY KEY (`ancestor`, `descendant`)
);
Run Code Online (Sandbox Code Playgroud)

将目录插入filesystem表中

INSERT INTO filesystem (id, dirname) VALUES (1, 'ROOT');
INSERT INTO filesystem (id, dirname) VALUES (2, 'Dir2');
INSERT INTO filesystem (id, dirname) VALUES (3, 'Dir3');
INSERT INTO filesystem (id, dirname) VALUES (4, 'Dir4');
INSERT INTO filesystem (id, dirname) VALUES (5, 'Dir5');
INSERT INTO filesystem (id, dirname) VALUES (6, 'Dir6');
INSERT INTO filesystem (id, dirname) VALUES (7, 'Dir7');
Run Code Online (Sandbox Code Playgroud)

创建闭包表路径

INSERT INTO tree_path (ancestor, descendant) VALUES (1, 1);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 2);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 3);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 4);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 5);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 6);
INSERT INTO tree_path (ancestor, descendant) VALUES (1, 7);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 2);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 4);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 5);
INSERT INTO tree_path (ancestor, descendant) VALUES (2, 7);
INSERT INTO tree_path (ancestor, descendant) VALUES (3, 3);
INSERT INTO tree_path (ancestor, descendant) VALUES (3, 6);
INSERT INTO tree_path (ancestor, descendant) VALUES (4, 4);
INSERT INTO tree_path (ancestor, descendant) VALUES (4, 7);
INSERT INTO tree_path (ancestor, descendant) VALUES (5, 5);
INSERT INTO tree_path (ancestor, descendant) VALUES (6, 6);
INSERT INTO tree_path (ancestor, descendant) VALUES (7, 7);
Run Code Online (Sandbox Code Playgroud)

运行一些查询

# (ROOT) and subdirectories
SELECT f.id, f.dirname FROM filesystem f
  JOIN tree_path t
    ON t.descendant = f.id
 WHERE t.ancestor = 1;

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  3 | Dir3    |
|  4 | Dir4    |
|  5 | Dir5    |
|  6 | Dir6    |
|  7 | Dir7    |
+----+---------+


# Dir3 and subdirectories
SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.descendant = f.id
 WHERE t.ancestor = 3;

+----+---------+
| id | dirname |
+----+---------+
|  3 | Dir3    |
|  6 | Dir6    |
+----+---------+

# Dir5 and parent directories
SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.ancestor = f.id
 WHERE t.descendant = 5;

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  5 | Dir5    |
+----+---------+

# Dir7 and parent directories
SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.ancestor = f.id
 WHERE t.descendant = 7;

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  4 | Dir4    |
|  7 | Dir7    |
+----+---------+

SELECT f.id, f.dirname
  FROM filesystem f
  JOIN tree_path t
    ON t.ancestor = f.id
 WHERE t.descendant = (
SELECT id
  FROM filesystem
 WHERE dirname LIKE '%7%'
);

+----+---------+
| id | dirname |
+----+---------+
|  1 | ROOT    |
|  2 | Dir2    |
|  4 | Dir4    |
|  7 | Dir7    |
+----+---------+
Run Code Online (Sandbox Code Playgroud)

  • 你的`tree_path`表不应该包含一个"嵌套级别"或"深度"字段来使它成为一个闭包表吗? (3认同)
  • 我首先阅读了查询并一直想知道“这是如何工作的?” 我意识到你的“tree_path”表是目录图的“传递闭包”的邻接列表表示,回答了以下问题:“这条路径是另一条路径的可达后代吗?” 和“这条路径是另一条路径的可达祖先吗?” 好的。 (2认同)
  • @seh:是的,这是一项非常好的技术。虽然它比简单的邻接列表需要更多的条目,但选择数据的查询要简单得多。但我不能相信这一点。如果您想了解更多信息,请查看我在该问题下的评论中发布的 Bill Karwin 链接。请注意,您还可以添加路径长度,这使得查找直系祖先/后代变得更简单。 (2认同)