3

我正在开发一个 python 程序,该程序允许用户通过将“标签”附加到文件来对文件进行分类。这些标签可以彼此处于层次关系中。例如,“猫”标签可以归类为“哺乳动物”标签的“后代”。因此,一旦文件被标记为“狗”,它也可以通过“哺乳动物”标签访问。

这些标签及其相互之间和与文件的关系显然需要存储在数据库中,而我最熟悉关系数据库。

我非常喜欢将树存储在关系数据库中的Modified Pre-order Tree Traversal方法,因为它不需要递归并且需要更少的数据库查询。

但是,我也想促进与多个父母的标签。例如,“狗”可以是“哺乳动物”的孩子,也可以是“四足动物”的孩子,其中并非所有四足动物都是哺乳动物甚至动物(例如桌子),“哺乳动物”和“四足动物” -thing' 标签没有“共同祖先”。

有谁知道在保持 MPTT 方法的一些优点的同时在数据库中表示这种关系的方法?

谢谢你的帮助。

4

1 回答 1

2

您所描述的是无环有向图,而不是树,因此您不能使用任何像 MPTT 这样的 sql“树存储”方法。这是一篇演示此问题的邻接列表方法的文章。

但是,我强烈建议您不要走这条路,不是因为实施困难,而是因为您最终会让用户感到困惑和沮丧。根据我的经验,用户对复杂的本体系统使用不当,很容易被它们混淆。要么使用没有父子关系的平面“标签”命名空间,要么使用每个节点最多有一个父节点的树形排列。

但是如果你想要一个图表,他最直接的方法是有一个这样的表格:

CREATE TABLE tag_relationships (
    tag_child_id INTEGER NOT NULL REFERENCES tags (id) ON UPDATE CASCADE ON DELETE CASCADE,
    tag_parent_id INTEGER NOT NULL REFERENCES tags (id) ON UPDATE CASCADE ON DELETE CASCADE,
    PRIMARY KEY (tag_child_id, tag_parent_id)
);

您可能无法避免递归查询。当您想要创建匹配搜索时,使用您拥有的标签作为搜索条件并递归添加子标签,直到您拥有完整的标签列表。

您还必须小心创建循环。添加关系时,需要递归访问父节点,并确保不会两次出现在同一个节点。

为了避免递归查询和帮助检测循环,您可以做的事情是通过使每个节点的所有关系都显式化来稍微非规范化您的数据。我的意思是,假设 A 是 B 和 C 的孩子,C 是 D 的孩子。

而不是表示这一事实所需的最小边数:

tag_child_id  tag_parent_id
A             B
A             C
C             D

您将使所有隐式关系(必须通过递归找到的)显式:

A             B
A             C
A             D
C             D

请注意,我添加了(A, D).

于 2012-07-19T21:32:47.427 回答