nosql数据库中的树结构

时间:2010-07-19 13:56:55

标签: google-app-engine google-cloud-datastore nosql bigtable

我正在为Google App Engine开发一个应用程序,该应用程序将BigTable用于其数据存储区。

这是一个关于合作编写故事的应用程序。这是一个非常简单的爱好项目,我正在努力寻找乐趣。它是开源的,你可以在这里看到它:http://story.multifarce.com/

这个想法是任何人都可以写一个段落,然后需要由另外两个人进行验证。故事也可以在任何段落中分支,以便故事的另一个版本可以在另一个方向继续。

想象一下以下树结构:

每个数字都是一个段落。我希望能够选择每个独特故事情节中的所有段落。基本上,那些独特的故事情节是(2,7,2); (2,7,6,5); (2,7,6,11)和(2,5,9,4)。忽略节点“2”出现两次,我只是从维基百科中获取了一个树形结构图。

我还提出了一个建议解决方案的图表:https://docs.google.com/drawings/edit?id=1fdUISIjGVBvIKMSCjtE4xFNZxiE08AoqvJSLQbxN6pc&hl=en

如何设置结构对于写入既有效率又有效,但最重要的是阅读?

2 个答案:

答案 0 :(得分:16)

有许多众所周知的方法可以在数据库中表示树木;他们每个人都有自己的优点和缺点。以下是最常见的:

  • Adjacency list,其中每个节点都存储其父节点的ID。
  • Materialized path,这是Keyur描述的策略。这也是App Engine中的实体组(例如,父实体)使用的方法。它或多或少都是您在更新中描述的内容。
  • Nested sets,其中每个节点都有“左”和“右”ID,以便所有子节点都包含在该范围内。
  • 使用根ID进行协调的邻接列表。

每一种都有其优点和缺点。邻接列表很简单,更新便宜,但需要多个查询来检索子树(每个父节点一个)。增强的邻接列表可以通过在每个记录中存储根节点的ID来检索整个树。

物化路径易于实现且更新成本低,并且允许查询任意子树,但会对深树施加更多的开销。

嵌套集更难实现,并且每次插入时平均需要更新一半节点。它们允许您查询任意子树,而不会增加具有物理化路径的密钥长度。

在你的特定情况下,你似乎根本不需要一个树形结构:每个故事,尽管可能是原始分支,但却是独立的。我建议使用“故事”模型,其中包含其段落的键列表(例如,在Python中为db.ListProperty(db.Key))。要渲染故事,您需要获取故事,然后对所有段落进行批量提取。要分支故事,只需复制故事条目 - 保持对段落的引用不变。

答案 1 :(得分:0)

我能想到的一个解决方案是 - 节点的路径也是该节点的关键。所以节点11的关键是“2/7/6/11”。您可以通过路径中所有键的简单键查找来遍历路径 - “2/7/6/11”,“2/7/6”,“2/7”,“2”