在嵌套集中移动节点

在嵌套集中移动节点,第1张

嵌套集中移动节点

我知道,这个主题已经很老了,但是无论如何仍然没有答案。我是从Google来到这里的,没有找到这个问题的直接答案。

因此,经过一些研究,我发现了很简单的解决方案。

一切,我们需要移动节点的是:节点左右位置,新父节点右边位置。然后可以通过四个简单步骤将节点移动到新位置:

  1. 将节点及其所有子节点的位置更改为负值,该值等于模块中的当前值。
  2. 将所有位置“向上”移动,更多,即当前节点的pos_right。
  3. 将所有位置“向下”移动更多,即新父节点的pos_right。
  4. 更改当前节点及其所有子节点的位置,以使它现在恰好在新父节点的“之后”(或“向下”)。

这是理论,现在-这种算法在MySQL中的实现(使用PHP的示例):

-- step 0: Initialize parameters.SELECT    @node_id := 1, --put there id of moving node     @node_pos_left := 0, --put there left position of moving node    @node_pos_right := 1, --put there right position of moving node    @parent_id := 2, --put there id of new parent node (there moving node should be moved)    @parent_pos_right := 4; --put there right position of new parent node (there moving node should be moved)SELECT    @node_size := @node_pos_right - @node_pos_left + 1; -- 'size' of moving node (including all it's sub nodes)-- step 1: temporary "remove" moving nodeUPDATE `list_items`SET `pos_left` = 0-(`pos_left`), `pos_right` = 0-(`pos_right`)WHERe `pos_left` >= @node_pos_left AND `pos_right` <= @node_pos_right;-- step 2: decrease left and/or right position values of currently 'lower' items (and parents)UPDATE `list_items`SET `pos_left` = `pos_left` - @node_sizeWHERe `pos_left` > @node_pos_right;UPDATE `list_items`SET `pos_right` = `pos_right` - @node_sizeWHERe `pos_right` > @node_pos_right;-- step 3: increase left and/or right position values of future 'lower' items (and parents)UPDATE `list_items`SET `pos_left` = `pos_left` + @node_sizeWHERe `pos_left` >= IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_size, @parent_pos_right);UPDATE `list_items`SET `pos_right` = `pos_right` + @node_sizeWHERe `pos_right` >= IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_size, @parent_pos_right);-- step 4: move node (ant it's subnodes) and update it's parent item idUPDATE `list_items`SET    `pos_left` = 0-(`pos_left`)+IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_pos_right - 1, @parent_pos_right - @node_pos_right - 1 + @node_size),    `pos_right` = 0-(`pos_right`)+IF(@parent_pos_right > @node_pos_right, @parent_pos_right - @node_pos_right - 1, @parent_pos_right - @node_pos_right - 1 + @node_size)WHERe `pos_left` <= 0-@node_pos_left AND `pos_right` >= 0-@node_pos_right;UPDATE `list_items`SET `parent_item_id` = @parent_idWHERe `item_id` = @node_id;

请注意-SQL代码中仍然可能存在一些语法错误,因为我实际上是在PHP中使用这种算法,如下所示:

$iItemId = 1;$iItemPosLeft = 0;$iItemPosRight = 1;$iParentId = 2;$iParentPosRight = 4;$iSize = $iPosRight - $iPosLeft + 1;$sql = array(    // step 1: temporary "remove" moving node    'UPDATE `list_items`    SET `pos_left` = 0-(`pos_left`), `pos_right` = 0-(`pos_right`)    WHERe `pos_left` >= "'.$iItemPosLeft.'" AND `pos_right` <= "'.$iItemPosRight.'"',    // step 2: decrease left and/or right position values of currently 'lower' items (and parents)    'UPDATE `list_items`    SET `pos_left` = `pos_left` - '.$iSize.'    WHERe `pos_left` > "'.$iItemPosRight.'"',    'UPDATE `list_items`    SET `pos_right` = `pos_right` - '.$iSize.'    WHERe `pos_right` > "'.$iItemPosRight.'"',    // step 3: increase left and/or right position values of future 'lower' items (and parents)    'UPDATE `list_items`    SET `pos_left` = `pos_left` + '.$iSize.'    WHERe `pos_left` >= "'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iSize : $iParentPosRight).'"',    'UPDATE `list_items`    SET `pos_right` = `pos_right` + '.$iSize.'    WHERe `pos_right` >= "'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iSize : $iParentPosRight).'"',    // step 4: move node (ant it's subnodes) and update it's parent item id    'UPDATE `list_items`    SET        `pos_left` = 0-(`pos_left`)+'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iItemPosRight - 1 : $iParentPosRight - $iItemPosRight - 1 + $iSize).',        `pos_right` = 0-(`pos_right`)+'.($iParentPosRight > $iItemPosRight ? $iParentPosRight - $iItemPosRight - 1 : $iParentPosRight - $iItemPosRight - 1 + $iSize).'    WHERe `pos_left` <= "'.(0-$iItemPosLeft).'" AND i.`pos_right` >= "'.(0-$iItemPosRight).'"',    'UPDATE `list_items`    SET `parent_item_id` = "'.$iParentItemId.'"    WHERe `item_id`="'.$iItemId.'"');foreach($sql as $sqlQuery){    mysql_query($sqlQuery);}

还请注意,代码可能已经过优化,但是为了更好的可读性,我将其保留下来。如果在多用户系统中使用嵌套集,还应考虑使用表锁定。

希望我的信息能对任何寻求我解决方案的人有所帮助。也欢迎任何评论和更正。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5022676.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-15
下一篇 2022-11-15

发表评论

登录后才能评论

评论列表(0条)

保存