ホームページ  >  記事  >  バックエンド開発  >  ツリーデータ構造格納方式(CUD)

ツリーデータ構造格納方式(CUD)

藏色散人
藏色散人転載
2019-09-10 11:31:162811ブラウズ

前の記事では、ネストされたコレクションのデータ モデルとクエリ メソッド、ポータルについて簡単に紹介しました。 ツリー データ構造の保存メソッド (クエリ)

Create

ネストされたコレクション モデルでは、各データは実際にはノードであり、各ノードは 2 ビット値を占有します。たとえば、スマートフォンの第 1 レベルのノードを追加することから始めましょう。

INSERT INTO `categories` (`title`, `lft`, `rgt`) VALUES('Smartphones', 1, 2);

スマートフォン メイン ノード (ルート) として、その lft は 1 である必要があり、コレクション内の子要素の数が増加するにつれて rgt の値も増加します。

次に、Smartphones 内に子要素 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 カテゴリに分類される必要があります。

ツリーデータ構造格納方式(CUD)

ノードの移動を実現するには、次の 3 つの手順が必要です:

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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はlearnku.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。