【问题标题】:DataBase (datamodel) to build a folder structureDataBase(数据模型)建立文件夹结构
【发布时间】:2026-01-14 08:40:01
【问题描述】:

计划在 Java 中构建基于文件夹的结构。

我将为 GUI 使用 jquery 插件,因此我不需要有关如何显示文件夹结构的信息。

我正在寻找有关如何存储文件夹信息的后端逻辑,以便可以快速有效地检索它。

每个文件夹将有多个子文件夹。 从叶子文件夹中,我们应该能够快速有效地访问根目录

例子:

+Folder1
  |__SubFolder1_1
  |__SubFolder1_2
        |_SubSubFolder1_2_1
        |_
+Folder2
  |__SubFolder2_1
        |_SubFolder2_1_1
        |_SubFolder2_1_2
             |_SubFolder2_1_2_1

可以随机添加新文件夹。 文件夹可以重命名。 文件夹可以删除。

我的问题是:

这些文件夹详细信息将如何存储在数据库中?

再次,我正在寻找一种快速有效的方法来存储和检索此信息。

【问题讨论】:

  • 什么意思,从叶子,快速访问根? 根目录,还是该文件夹的包含文件夹?在任何情况下,似乎正常的 parent_id 机制都可以工作,但不知道您在做什么类型的操作,很难说如何高效。
  • 你认为它需要多快?既然你提到了 jQuery,它听起来就像一个网络应用程序。网络速度将使基于索引 ID 的数据库查找相形见绌。

标签: java algorithm directory


【解决方案1】:

这是个好问题,但如果没有很多细节,很难谈论“最佳”解决方案。

您可以将其映射到如何在关系数据库中存储 n 叉树的抽象问题。

以下是一些影响问题的变量:

  1. 目录结构的总大小是多少?
  2. 有多少个单独的 VM 对结构执行写入操作?
  3. 移动操作是否频繁?
  4. 故障整个子树也是一项重要的操作吗?
  5. 您的数据库是否支持树遍历,或者您是否需要适用于任何合理关系数据库的解决方案?

以下假设您的数据库没有执行树遍历的特殊规定。

n 叉树有两种纯持久性模型。

第一种是简单的给每个节点写一个父引用:

| NodeId | ParentId | Name       | ....
|--------|----------|------------|-----

这种方法简化了文件夹的移动,但删除、查询所有嵌套的子文件夹和查找根目录变得昂贵。

第二种纯模型是将每个祖先关系与文件夹详细信息分开保存

| NodeId | Name     | ....
|--------|----------|------
...


| NodeId | AncestorId | Distance | 
|--------|------------|----------|
...

在这里,文件夹 /food/dairy/cheese/cheddar 将产生

| NodeId | Name     |
|--------|----------|
| #0     | (root)   |
| #1     | food     |
| #2     | dairy    |
| #3     | cheese   |
| #4     | cheddar  |


| NodeId | AncestorId | Distance |
|--------|------------|----------|
| #1     | #0         | 1        |
| #2     | #0         | 2        |
| #2     | #1         | 1        |
| #3     | #0         | 3        |
| #3     | #1         | 2        |
| #3     | #2         | 1        |
| #4     | #0         | 4        |
| #4     | #1         | 3        |
| #4     | #2         | 2        |
| #4     | #3         | 1        |

这种方法对于移动来说非常昂贵,并且一个新目录会导致d 插入,其中d 是与根的距离。但是子树列表是单个查询。祖先路径也是单个查询; order by Distance desc 可以让您快速到达根目录和第一个文件夹。

但仔细阅读您的问题,第一种方法的变体,简单地添加 root 也可能是您的正确方法:

| NodeId | ParentId | RootId | Name       | ....
|--------|----------|--------|------------|-----

请注意,移动文件夹会很昂贵,因为您需要确定所有嵌套的子文件夹,并更新所有这些记录的 RootId。

【讨论】:

  • 谢谢,我将结合使用您的答案和@AdrianShum 提供的答案。由于我将使用更多阿德里安的答案,我会将他标记为正确答案
【解决方案2】:

对于存储在数据库中,最简单和最直接的方法是为每个文件夹/节点设置一个 parent_folder_id。这在大多数情况下应该已经足够了,尤其是您要构建文件夹对象结构并根据对象模型进行操作。

取决于你的要求,有一个很常见的情况是你需要

  1. 找出某个文件夹下的所有子文件夹
  2. 通过 SQL 直接从 DB 执行查找。

如果它是你要找的,那么有一个有趣的方法你可以看看: 每个 DB 记录会有 2 个额外的数字字段,我们称之为 LEFT 和 RIGHT

假设一棵树是这样的:

ROOT
  + A
  | + A1
  | + A2
  + B
    + B1

将要存储在 DB 中的是

Node  LEFT  RIGHT  ... other fields
ROOT   1    12
A      2    7
A1     3    4
A2     5    6
B      8    11
B1     9    10
  • 每个父节点的 LEFT = 第一个子节点的 LEFT - 1,RIGHT = 最后一个子节点的 RIGHT + 1
  • 叶节点的 LEFT 和 RIGHT 将是 2 个连续的数字
  • 每个节点的 LEFT 应该是 = 前一个兄弟节点的 RIGHT + 1,RIGHT = 下一个兄弟节点的 LEFT - 1

当你需要通过SQL查找某个节点(N)下的所有节点时,只需找出所有LEFT > N.LEFT和RIGHT

您可以通过批量更新相关节点来轻松执行插入/删除(这不是一项艰巨的任务,留给您:P)

这可能对OO不太友好,但如果我提到的需求是你需要的,你可以考虑使用这种方法。

【讨论】:

    【解决方案3】:

    链表,在此处的 Java API 中记录:

    http://download.oracle.com/javase/6/docs/api/java/util/LinkedList.html

    作为一般的计算机科学结构,请阅读以下内容:

    http://en.wikipedia.org/wiki/Linked_list

    希望对你有帮助

    【讨论】:

    • 其实更像是一棵树,比如“目录树”。
    • @DaveNewton 谢谢,但我正在寻找有关如何将信息存储在数据库(数据模型)中的信息,以便我可以快速存储/检索数据。
    • @kensenjohn 是的,“快速”取决于您尝试检索的方式/内容。
    【解决方案4】:

    对于数据库,保持简单。一个名为文件夹的表 - 唯一的列是 Id、Name、ParentId。现在每个文件夹都有一个父文件夹,有些文件夹会有子文件夹。加载孩子:

    SELECT * FROM Folder WHERE Id == ParentFolderId
    

    【讨论】: