मैं देखता हूं, कि यह विषय काफी पुराना है, लेकिन फिर भी यह अभी भी अनुत्तरित है। मैं यहां Google से आया हूं, और इस प्रश्न का कोई सीधा उत्तर नहीं मिला।
तो, थोड़ा शोध करने के बाद मुझे काफी आसान समाधान मिला।
सब कुछ, जो हमें अपने नोड को स्थानांतरित करने की आवश्यकता है वह है:नोड लेफ्ट और राइट पोजीशन, नया पैरेंट नोड राइट पोजिशन। फिर नोड को नई स्थिति में चार आसान चरणों में ले जाया जा सकता है:
- नोड और उसके सभी उप नोड्स की स्थिति को नकारात्मक मानों में बदलें, जो मॉड्यूल द्वारा वर्तमान के बराबर हैं।
- सभी पदों को "ऊपर" ले जाएं, जो वर्तमान नोड के उस स्थिति से अधिक हैं।
- सभी पदों को "नीचे" ले जाएं, जो अधिक हैं, जो कि नए पैरेंट नोड के pos_right हैं।
- वर्तमान नोड और उसके सभी सबनोड्स की स्थिति बदलें, ताकि यह अब बिल्कुल नए पैरेंट नोड के "बाद" (या "डाउन") हो।
यह सिद्धांत है, अब - 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 node
UPDATE `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_size
WHERE `pos_left` > @node_pos_right;
UPDATE `list_items`
SET `pos_right` = `pos_right` - @node_size
WHERE `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_size
WHERE `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_size
WHERE `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 id
UPDATE `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` <= [email protected]_pos_left AND `pos_right` >= [email protected]_pos_right;
UPDATE `list_items`
SET `parent_item_id` = @parent_id
WHERE `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);
}
कृपया यह भी ध्यान दें, उस कोड को अनुकूलित किया जा सकता है, लेकिन मैं इसे बेहतर पठनीयता के लिए ऐसे ही छोड़ने जा रहा हूं। यदि आप बहु-उपयोगकर्ता सिस्टम में नेस्टेड सेट का उपयोग कर रहे हैं तो टेबल लॉकिंग पर भी विचार करें।
आशा है कि मेरा संदेश किसी की भी मदद करेगा, जो मेरे बाद समाधान खोजेगा। किसी भी टिप्पणी और सुधार का भी स्वागत है।