1. 程式人生 > 程式設計 >在巢狀集模型中改變節點的父親節點

在巢狀集模型中改變節點的父親節點

什麼是巢狀集模型

詳情可以看我在掘金上的這篇文章,juejin.im/post/5d2288…

大致上來說,它就是一種層級結構的模型。當對層級結構有許多的遍歷操作時,使用它會十分方便。比如獲取某個節點到根節點的路徑,統計節點的子節點數量,或者節點及其子節點所關聯的實體數量(如獲取產品分類樹,及其每個分類節點所擁有的產品數量)。

不過它的缺點是增加、刪除、移動節點會相對而言較為複雜以及消耗效能。 尤其是移動節點,更加複雜。然而在實際應用場景當中,改變某個分類的父分類是一個比較常見的需求。下面我們就來介紹該如何實現這個需求。

如何改變節點的父親節點

我們以如下的分類樹為例子:

如果我們想讓遊戲節點的父節點改成音樂

節點,可以按照以下步驟:

  1. 給子樹建立新的空間
UPDATE category SET lft = lft + :width WHERE lft >= :newpos
UPDATE category SET rgt = rgt + :width WHERE rgt >= :newpos
複製程式碼
  1. 把子樹移動到新空間
UPDATE tags SET lft = lft + :distance,rgt = rgt + :distance
   WHERE lft >= :tmppos AND rgt < :tmppos + :width
複製程式碼
  1. 去除被之前子樹佔據的空間
UPDATE category SET lft = lft - :width WHERE lft > :oldRgt
UPDATE category SET rgt = rgt - :width WHERE rgt > :oldRgt
複製程式碼

各變數說明

int newpos = 4 + 1  // 新的父節點的lft值+1;在這裡音樂節點的lft值是4
int width = node.getRgt() - node.getLft() + 1; // 原子樹的寬度
int distance = newpos - node.getLft(); // 節點到新的位置的距離
int tmppos = node.getLft();

// 向後移動必須考慮新空間
if
(distance < 0) { distance -= width; tmppos += width; } 複製程式碼

再經過上面的操作後,整個樹將會變成如下:

總結

除了上面的5次sql操作,其實我們還需要查詢被移動的節點以及新的父節點。所以總的來說至少需要6次sql查詢。一般情況下,修改節點的父節點是一個不太頻繁的操作,所以相對於它帶來的好處,其實是可以接受這樣的效能消耗的。