我正在尝试使用Propel的NestedSet功能。但是,我遗漏了一些关于插入的问题,即树在创建时是平衡的(即水平填充)。
说我有这些元素:
root
r1c1 r1c2
r2c1 r2c2
我想插入r2c3作为r1c2的第一个子节点(即在第3行开始之前填充第2行)。
我的第一个尝试就是创建这个功能:
function where(User $root,$depth=0)
{
$num = $root->getNumberOfDescendants();
if ( $num < 2 )
return $root;
foreach($root->getChildren() as $d)
{
if ( $d->getNumberOfChildren() < 2 )
{
return $d;
}
}
foreach($root->getChildren() as $d)
{
return where($d, $depth+1);
}
}
但是,这会在r2c1上插入一个孩子,而不是我想要的r1c2。
有没有办法以某种方式在下一个可用位置插入树?
TIA 麦克
答案 0 :(得分:0)
好的,感谢http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/,我发现这个算法会做我想要的:
function where($root)
{
$num = $root->getNumberOfDescendants();
if ( $num < 2 )
return $root;
$finder = DbFinder::from('User')->
where('LeftId','>=',$root->getLeftId())->
where('RightId','<=',$root->getRightId())->
whereCustom('user.RightId = user.LeftId + ?',1,'left')->
whereCustom('user.RightId = user.LeftId + ?',3,'right')->
combine(array('left','right'),'or')->
orderBy('ParentId');
return $finder->findOne();
}
它基本上执行这个SQL:
SELECT u.*
FROM user u
WHERE u.LEFT_ID >= $left AND u.RIGHT_ID <= $right AND
(u.RIGHT_ID = u.LEFT_ID+1 OR u.RIGHT_ID = u.LEFT_ID+3)
ORDER BY u.PARENT_ID
LIMIT 1
一片叶子有RIGHT = LEFT + 1,一个有一个孩子的节点有RIGHT = LEFT + 3。通过添加ORDER BY u.PARENT_ID,我们可以找到树中可用的最高节点。如果您使用LEFT_ID或RIGHT_ID,则不会平衡树。