Struktura drzewiasta w bazie danych Odc. 6 Nested set – przenoszenie gałęzi

SQL Zostaw komentarz

W przypadku najprostszej implementacji struktury drzewiastej w bazie, jaką opisałam w pierwszym artykule tej serii, przeniesienie całej gałęzi do nowej lokalizacji jest zagadnieniem trywialnym. Wystarczy zmienić wartość parametru ‘parentID’ odpowiedniego rekordu i już. Jeśli chodzi o drzewo typu nested set, nie jest to już takie proste. Przeniesienie gałęzi wymaga przeliczenia parametrów ‘lft’ i ‘rgt’ wielu rekordów. Przypomina to trochę znaną zabawę w przesuwane puzzle. Aby przesunąć grupę rekordów stanowiących gałąź do nowej lokalizacji, trzeba dla niej zrobić miejsce przesuwając inną grupę rekordów.

Nieco teorii

Na czym dokładnie ma polegać ta operacja, najłatwiej będzie zrozumieć analizując omawiane już wcześniej drzewo przedstawione za pomocą płaskiej perspektywy. Załóżmy więc, że chcemy przenieść gałąź opartą na elemencie ‘office’ (lft=3 rgt=10) tak, aby stała się elementem podrzędnym dla elementu ‘Linux’, tuż za elementem ‘Iceweasel’, tak jak to pokazano na rysunku poniżej.

Przesuwana gałąź składa się z czterech rekordów, wobec czego rezerwuje dla siebie osiem unikalnych wartości parametrów ‘lft’ i ‘rgt’. Aby ją przesunąć w wyznaczone miejsce należy między parametrami ‘rgt=16′ a ‘rgt=17′ zrobić odpowiednio dużo wolnego miejsca. W tym celu wszystkie parametry ‘lft’ i ‘rgt’ o wartościach od 11 do 16 należy zmniejszyć właśnie o wartość 8. W ten sposób powstanie luka w którą będzie można wstawić naszą gałąź.

Jak widać na powyższym rysunku wymagało to przeliczenia wartości sześciu parametrów ‘lft’ i ‘rgt’ i właśnie o tyle trzeba zwiększyć wartości parametrów ‘lft’ i ‘rgt’ dla wszystkich rekordów przesuwanej gałęzi, aby znalazła się ona w pożądanym miejscu.

Komplet niezbędnych zapytań

Operacja przesunięcia gałęzi wymaga jeszcze większej ilości zapytań niż dodanie rekordu, oznacza to, iż również tym razem należy wpierw zablokować tabelę wykonując zapytanie:


LOCK TABLES tree WRITE

W następnej kolejności należy wykonać zapytanie które pomoże nam uzyskać lukę w odpowiednim miejscu i przesunie część rekordów, tak jak zostało to wcześniej opisane:


UPDATE tree SET `lft` = `lft` - 8 WHERE `lft` >= 11 AND `lft` <=16
UPDATE tree SET `rgt` = `rgt` - 8 WHERE `rgt` >= 11 AND `rgt` <=16

Po przesunięciu części rekordów i zwolnieniu miejsca na przenoszoną gałąź należy wykonać zapytania, które przeliczą parametry ‘lft’ i ‘rgt’ wszystkich elementów gałęzi.


UPDATE main_tree SET `lft` = `lft` + 6 WHERE `id` IN(5,8,9,10)
UPDATE main_tree SET `rgt` = `rgt` + 6 WHERE `id` IN(5,8,9,10)

Dociekliwy czytelnik zauważy zapewne, że tym razem warunek, na podstawie którego wybierane są modyfikowane rekordy, nie dotyczy wartości parametrów ‘lft’ i ‘rgt’. Zapobiega to ponownemu, a więc błędnemu przetworzeniu rekordów zmodyfikowanych w poprzednim kroku. Dlatego waśnie w tym kroku należy precyzyjnie wskazać identyfikatory rekordów należących do przesuwanej gałęzi.

W ostatnim kroku wystarczy już tylko odblokować tabelę:


UNLOCK TABLES

Praca domowa

W tym artykule pokazałam tylko ideę algorytmu pozwalającego przesuwać całe gałęzie w obrębie drzewa, oraz zapytania realizujące konkretny wariant tej operacji. Obsługę tego algorytmu od strony php, czyli rozstrzygnięcie jak uzyskać zestaw wartości parametrów ‘id’ wszystkich elementów drzewa, jak określić które rekordy trzeba przeliczyć aby zrobić miejsce dla przesuwanej gałęzi oraz obliczenie o jaką wartość należy zmienić wartości parametrów ‘lft’ i ‘rgt’ w poszczególnych krokach operacji, pozostawiam inwencji twórczej czytelnika, który będzie chciał z przedstawionego tu modelu skorzystać. To tak w ramach pracy domowej.

Poleć wpis na:

  • Facebook
  • Technorati
  • Wykop

Podobne artykuły:

  1. Struktura drzewiasta w bazie danych Odc. 5 Nested set – dodawanie rekordu
  2. Struktura drzewiasta w bazie danych Odc. 4 Nested set – odczytywanie gałęzi
  3. Struktura drzewiasta w bazie danych Odc. 3 Nested set – odczytywanie struktury drzewa
  4. Struktura drzewiasta w bazie danych Odc. 2 Konstrukcja drzewa typu nested set
  5. Struktura drzewiasta w bazie danych Odc. 1

Komentarze (6) do “Struktura drzewiasta w bazie danych Odc. 6 Nested set – przenoszenie gałęzi”

  1. Vokiel Says:

    Muszę przyznać, że zrobiłaś kawał dobrej roboty. Śledziłem Twoje wpisy w tej kategorii od początku. Szczerze wątpiłem, że dasz radę pociągnąć taki rozbudowany temat, tak dokładnie go opisać, przedstawić na przykładach.
    Gratuluję samozaparcia.
    Pozdrawiam

  2. Joanna Says:

    Dziękuję za miłe słowa. Temat rozmontowywałam, bo było mi to potrzebne w pracy, a poza tym jest to dość ciekawe zagadnienie. Uznałam, że szkoda by było, nie podzielić się wiedzą.

    Można było mieć wątpliwości czy doprowadze temat do konca, bo miałam spora przerwę (macierzyńską). No ale jak widac wracam do pracy.

    W sumie to pozostał jeszcze jeden tamat, kasowanie, ale jak ktoś się upora z przesuwaniem gałęzi, to kasowanie będzie dla niego drobnostką.

    Oczywiście zagadnienie nie jest wyczerpane. Szczególnie, że nie pokazałam rozwiązań na poziomie PHP. Zrobiłam to celowo, żeby nie zaciemniać i nie komplikować. Jednak, kto wie. Może się kiedyś o to pokuszę.

  3. kondor Says:

    Dziekuję Joanno za 6 odcinkowa lekcję.
    Od poł roku przymierzałem się do muśnięcia tego tematu, a Ty podałas go mi na przysłowiowym talerzu.

    Krótko , zwięźle i na temat.
    Pozdrawiam
    Kondor

  4. ciekawski Says:

    Jaką metodę drzewa polecasz do komentarzy? Coś na zasadzie zagnieżdżonych komentarzy jak w WP?

  5. Joanna Says:

    Ponieważ najprawdopodobniej nie będziesz edytował tego drzewa i zmieniał jego struktury a jedynie komentarze będą dodawane i usuwane to tym bardziej skłaniałabym się do metody nested set, ale ja jestem ta metodą zafascynowana :) więc mogę być nieobiektywna.

  6. ciekawski Says:

    Niestety czasem zajdzie potrzeba edycji/usunięcia komentarzy, lecz będzie to raczej rzadkie zjawisko:)

Zostaw komentarz

Silnik: Wordpress - Theme autorstwa N.Design Studio. Spolszczenie: Adam Klimowski.
RSS wpisów RSS komentarzy Zaloguj się