【问题标题】:Storing a deep directory tree in a database在数据库中存储深层目录树
【发布时间】:2019-03-19 17:27:46
【问题描述】:

我正在开发一个桌面应用程序,它很像 WinDirStat 或 voidtools 的 Everything - 它映射硬盘驱动器,即从目录树中创建一个深度嵌套的字典。

然后桌面应用程序应该将目录树存储在某种数据库中,以便可以使用 Web 应用程序从根目录逐个深度地浏览它们。

假设两个应用程序暂时在同一台机器上本地运行。

想到的问题是应该如何构建数据以及应该使用什么数据库,考虑: 1)RAM消耗应该是合理的 2) 目录准备好在 Web 应用程序中查看所需的时间应该最短

P.S- 我最初的方法是将每个文件系统节点分别序列化为 JSON 并将每个节点插入到 Mongo 中,对象引用将它们链接到它们的子节点。这样,Web 应用程序可以轻松地根据用户需求加载数据。 但是,我担心为 Mongo 制作这么多(平均为 100 万)独立插入会花费很多时间;如果我进行批量插入,这意味着我必须将每个批量保存在内存中。

我还考虑将整个树转储为一个深度嵌套的 JSON,但数据太大而不能成为 Mongo 文档。 GridFS 可用于存储它,但我会在 Web 应用程序中加载整个树,即使深层节点可能不感兴趣。

【问题讨论】:

  • 另外:请参阅我的这个旧线程,其中提供了一些关于如何将树存储在关系数据库中的好建议。 stackoverflow.com/questions/192220/…
  • 是否需要为更高的节点(而不是叶子)保留一些信息? IE。所有子节点中内容的总大小是多少?
  • 是的,越高的节点越相关。想想您的 Windows 资源管理器视图,从 C: 开始,按需进行更深入。不确定您指的是什么数据,但每个节点都包含几个字段(例如名称、大小、属性),并且通常总共有超过一百万个节点

标签: database mongodb data-structures tree bigdata


【解决方案1】:

鉴于您的要求:

  • A) RAM 使用率低
  • B) 在 Mongo 中满足文件大小限制
  • C) 响应式 UI

我会考虑以下几点。

以这个目录为例

C:\
C:\X\
C:\X\B\
C:\X\file.txt
C:\Y\
C:\Y\file.pdf
C:\Y\R\
C:\Y\R\file.js

在 JSON 中它可能表示为:

{
    "C:": {
        "X": {
            "B": {},
            "file.txt": "file information..."
        },
        "Y": {
            "file.pdf": "file information...",
            "R": {
                "file.js": "file information..."
            }
        }
    }
}

正如您所指出的,后者不能很好地适应大型目录结构(我可以直接告诉您,浏览器不会欣赏 JSON blob 代表即使是包含几千个文件/文件夹的普通目录)。前者虽然类似于一些实际的文件系统并且在正确的上下文中高效,但在与 JSON 之间进行转换时会很痛苦。

我的建议是将每个目录分成一个单独的 JSON 文档,因为这将解决所有三个问题,但是没有什么是免费的,这会增加代码复杂性、每个会话的请求数量等。

上面的结构可以分解成以下文件:

[
    {
        "id": "00000000-0000-0000-0000-000000000000",
        "type": "d",
        "name": "C:",
        "children": [
            "11111111-1111-1111-1111-111111111111",
            "22222222-2222-2222-2222-222222222222"
        ]
    },
    {
        "id": "11111111-1111-1111-1111-111111111111",
        "type": "d",
        "name": "X",
        "children": [
            "33333333-3333-3333-3333-333333333333",
            "55555555-5555-5555-5555-555555555555"
        ]
    },
    {
        "id": "22222222-2222-2222-2222-222222222222",
        "type": "d",
        "name": "Y",
        "children": [
            "44444444-4444-4444-4444-444444444444",
            "66666666-6666-6666-6666-666666666666"
        ]
    },
    {
        "id": "33333333-3333-3333-3333-333333333333",
        "type": "d",
        "name": "B",
        "children": []
    },
    {
        "id": "44444444-4444-4444-4444-444444444444",
        "type": "d",
        "name": "R",
        "children": [
            "77777777-7777-7777-7777-777777777777"
        ]
    },
    {
        "id": "55555555-5555-5555-5555-555555555555",
        "type": "f",
        "name": "file.txt",
        "size": "1024"
    },
    {
        "id": "66666666-6666-6666-6666-666666666666",
        "type": "f",
        "name": "file.pdf",
        "size": "2048"
    },
    {
        "id": "77777777-7777-7777-7777-777777777777",
        "type": "f",
        "name": "file.js",
        "size": "2048"
    }
]

每个文档代表一个目录或文件以及(如果是目录)它的直接子 ID。子项可以使用它们的 ID 延迟加载,并在 UI 中附加到它们的父项。实施良好的延迟加载可以将子节点预加载到所需的深度,从而创建一个响应速度非常快的 UI。 RAM 使用量很少,因为您的服务器只需处理每个请求的小负载。与单个文档方法相比,请求的数量确实增加了很多,但同样,一些巧妙的延迟加载可以聚集请求并减少总数。

更新 1:我在回答之前不知何故忽略了你的倒数第二段,所以这可能或多或少是你的想法。为了解决文档过多的问题,文档中的某些级别的集群节点可能是有序的。我现在得走了,但我会考虑一下。

更新 2:我已经创建了我提到的集群概念的简化版本的要点。它不考虑文件,只考虑文件夹,并且不包括更新文档的代码。希望它能给你一些想法,我会继续为我自己的目的更新它。

要点:tree_docs_cluster.js

【讨论】:

  • 经过大量研究后,我意识到这将是最好的方法。我对这种方法的唯一担心是一个接一个地插入这么多文档所花费的时间。我意识到我可以通过异步插入来加快速度,并且我可能会缓冲插入,因此它实际上不是逐个文档的。树本身按层次顺序插入(即顶层优先)
  • 这个问题让我很感兴趣,原因有很多。所以我一直在考虑文件数量的问题。到目前为止,我能想到的最好的是 AVL 树,其中每个节点都包含一个 cluster 目录节点,并且该树旨在松散 以块的形式遵循目录结构由文档大小、节点数等定义。与其他聚类方法相比,使用这样的树有利于对数据进行排序,以便请求返回包含兄弟节点的文档。当我有机会时,我会更新我的答案,更清楚地说明我的意思。
  • 感谢您的努力。我肯定会将我当前的代码与您的要点进行比较,以获得潜在的改进。我已经写了一个运行良好的概念证明(这正是我在之前的评论中描述的方式)
猜你喜欢
  • 2010-09-13
  • 2012-11-04
  • 2019-04-08
  • 2014-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多