codeIgniter闭包表模型

时间:2012-07-07 21:16:40

标签: php mysql codeigniter transitive-closure-table

这是我正在使用的课程:https://gist.github.com/2174233

我有两个表:一个表包含用户,另一个表包含闭包。

当我使用get_children()方法时(比如说来自root或其他父级),它只显示层次结构的第一级。我应该在lvl列中存储哪些值?

这是闭包表的定义,我有:

 CREATE TABLE closures (
     id         INT(11) NOT NULL AUTO_INCREMENT,
     ancestor   INT(11) NOT NULL,
     descendant INT(11) NOT NULL,
     lvl        INT(11) NOT NULL,

     PRIMARY KEY (id)
 )

以下是我存储在闭包表中的数据示例:

INSERT INTO `closures` (`id`, `ancestor`, `descendant`, `lvl`) 
VALUES (1, 1, 20, 0),
       (4, 20, 26, 0),
       (5, 26, 25, 0);

最后一个是lvl列,但我不知道,那里有什么价值。你能给我一个如何使用它的建议吗?

我必须存储的结构有3个级别:root - > 20节点 - > 26节点,但它只给我20个节点的第一级子节点。

1 个答案:

答案 0 :(得分:3)

我建议您选择SQL Antipatterns本书。第二章将闭包表作为实现类别树的推荐方法之一。

那就是说。看起来你的闭包表有点奇怪。 id列中没有任何意义。相反,你应该有一个复合主键,由唯一的祖先和后代值组成。

你还没有自己插入节点..只有两个不同节点之间的连接。也许阅读"Rendering Trees with Closure Tables"可以对这个主题有所启发。

猜测INSERT语句应如下所示(至少my conclusion}:

INSERT INTO closures(ancestor, descendant, lvl) 
VALUES (1,  1,  null),
       (20, 20, null),
       (26, 26, null),
       (28, 28, null),
       (1,  20, 1),
       (20, 26, 2),
       (26, 25, 3);

您必须了解的是,闭包表不存储树。相反,您正在使用的数据结构是方向图。像这样:

enter image description here

如您所见,此图表有三个根节点:3,5和7.另外,需要注意的是,节点10的深度级别不同,具体取决于你开始的根节点。

它将被定义为两个闭包:[3,10,1]和[11,10,2]。意思是,从第11个节点开始的连接会使它成为第2级,而从第3个节点开始,它是第一级项目。

事实是,当您使用闭包表时,每个类别可以有多个不同深度级别的父类别


加法(@ypercube):

我对“级别”或“深度”列的理解是它存储了从祖先到目标的“距离”(步骤)。它不是节点的绝对级别,因此闭包表可用于存储比树图更复杂的表。您甚至可以拥有从祖先到后代的多条路径,每条路径都有不同的步骤。

此外,Null应为0,还需要更多行。

所以,数据将是:

INSERT INTO closures(ancestor, descendant, lvl) 
VALUES ( 1,  1,  0), (20, 20, 0), (26, 26, 0), (25, 25, 0),
                     ( 1, 20, 1), (20, 26, 1), (26, 25, 1),
                                  ( 1, 26, 2), (20, 25, 2),
                                               ( 1, 25, 3) ;