이전 글에서는 중첩 컬렉션의 데이터 모델과 쿼리 방식을 간략하게 소개했습니다. 포털: 트리 데이터 구조 저장 방법(쿼리)
Create
중첩 컬렉션 모델에서는 각 데이터가 실제로 노드이고, 각 노드는 2비트 값을 차지합니다. 예를 들어 스마트폰의 첫 번째 레벨 노드를 추가하는 것부터 시작하겠습니다.
INSERT INTO `categories` (`title`, `lft`, `rgt`) VALUES('Smartphones', 1, 2);
스마트폰 기본 노드(루트)로서 lft는 1이어야 하며 컬렉션의 하위 요소가 증가함에 따라 rgt 값도 증가합니다.
이제 스마트폰 내부에 Android 하위 요소를 추가하려고 합니다. mysql 저장 프로시저를 사용하세요.
LOCK TABLE categories WRITE; SELECT @root_left := lft FROM categories WHERE title = 'Smartphones'; UPDATE categories SET rgt = rgt + 2 WHERE rgt > @root_left; UPDATE categories SET lft = lft + 2 WHERE lft > @root_left; INSERT INTO categories (title, lft, rgt) VALUES('Android', @root_left + 1, @root_left + 2); UNLOCK TABLES; SELECT `title`, `lft`, `rgt` FROM `categories`; +-------------+-----+-----+ | title | lft | rgt | +-------------+-----+-----+ | Smartphones | 1 | 4 | | Android | 2 | 3 | +-------------+-----+-----+
다시 Android에 Xiaomi 하위 요소를 추가하려고 합니다.
LOCK TABLE categories WRITE; SELECT @root_left := lft FROM categories WHERE title = 'Android'; UPDATE categories SET rgt = rgt + 2 WHERE rgt > @root_left; UPDATE categories SET lft = lft + 2 WHERE lft > @root_left; INSERT INTO categories (title, lft, rgt) VALUES('小米', @root_left + 1, @root_left + 2); UNLOCK TABLES; SELECT `title`, `lft`, `rgt` FROM `categories`; +-------------+-----+-----+ | title | lft | rgt | +-------------+-----+-----+ | Smartphones | 1 | 6 | | Android | 2 | 5 | | 小米 | 3 | 4 | +-------------+-----+-----+
이번에는 스마트폰에 하위 요소인 iOS를 추가하려고 하므로 이전에는 Android 요소를 추가해야 합니다. 여기에서 조정하세요. 저장된 프로세스를 살펴보고 Android의 오른쪽에 iOS를 삽입해 보겠습니다
LOCK TABLE categories WRITE; SELECT @next_right := rgt FROM categories WHERE title = 'Android'; UPDATE categories SET rgt = rgt + 2 WHERE rgt > @next_right; UPDATE categories SET lft = lft + 2 WHERE lft > @next_right; INSERT INTO categories(title, lft, rgt) VALUES('iOS', @next_right + 1, @next_right + 2); UNLOCK TABLES; SELECT `title`, `lft`, `rgt` FROM `categories`; +-------------+-----+-----+ | title | lft | rgt | +-------------+-----+-----+ | Smartphones | 1 | 8 | | Android | 2 | 5 | | 小米 | 3 | 4 | | iOS | 6 | 7 | +-------------+-----+-----+
Delete
노드를 삭제하는 경우 실제로는 노드를 추가하는 역과정으로 볼 수 있습니다. 노드의 넓은 세그먼트를 측정하기 위한 너비입니다. rgt - lft + 1이므로 다음과 같이 저장 프로시저를 작성할 수 있습니다.
LOCK TABLE categories WRITE; SELECT @delete_left := lft, @delete_right := rgt, @delete_width := rgt - lft + 1 FROM categories WHERE title = 'Android'; DELETE FROM categories WHERE lft BETWEEN @delete_left AND @delete_right; UPDATE categories SET rgt = rgt - @delete_width WHERE rgt > @delete_right; UPDATE categories SET lft = lft - @delete_width WHERE lft > @delete_right; UNLOCK TABLES; SELECT `title`, `lft`, `rgt` FROM `categories`; +-------------+-----+-----+ | title | lft | rgt | +-------------+-----+-----+ | Smartphones | 1 | 4 | | iOS | 2 | 3 | +-------------+-----+-----+
Update
노드 이동은 상대적으로 복잡한 프로세스입니다. 예를 들어, 아래 그림에서 macOS는 Unix 범주로 분류되어야 합니다.
노드의 이동을 구현하려면 다음 세 단계가 필요합니다.
1. 이동할 노드를 꺼냅니다.
2 lft 및 rgt 매개변수를 재정렬합니다.
3 노드를 지정된 위치로 이동합니다.
LOCK TABLE categories WRITE; -- 将要移动的节点摘出来,并且重新边篇 lft 和 rgt SELECT @move_left := lft , @move_right := rgt, @move_width := rgt - lft + 1 FROM categories WHERE title = 'macOS'; UPDATE categories SET rgt = -rgt WHERE lft BETWEEN @move_left AND @move_right; UPDATE categories SET lft = -lft WHERE lft BETWEEN @move_left AND @move_right; UPDATE categories SET rgt = rgt - @move_width WHERE rgt > @move_right; UPDATE categories SET lft = lft - @move_width WHERE lft > @move_right; -- 将节点放到 Unix 节点里 SELECT @root_left := lft FROM categories WHERE title = 'Unix'; UPDATE categories SET rgt = rgt + @move_width WHERE rgt > @root_left; UPDATE categories SET lft = lft + @move_width WHERE lft > @root_left; -- UPDATE categories SET lft = @root_left + 1 WHERE lft BETWEEN -@move_right AND -@move_left; UPDATE categories SET rgt = @root_left + 2 WHERE rgt BETWEEN -@move_right AND -@move_left; UNLOCK TABLES;
요약
실제로 SQL에서 중첩 세트의 데이터 모델은 오랫동안 제안되었으며 laravel-nestedset 또는 django-mptt등 많은 패키지에서 이 기능을 구현했습니다. 이 시리즈의 모든 사람에게 소개되어야 하는 닫힌 테이블이라는 데이터 모델과 같은 단순한 테이블 구조 디자인이나 기타 최적화는 확실히 없습니다.위 내용은 트리 데이터 구조 저장 방법(CUD)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!