F.15. ltree

本モジュールは階層ツリーを模擬した構造格納されたデータのラベルを表現する ltreeデータ型を実装します。 ラベルツリー全体を検索する高度な機能を提供します。

F.15.1. 定義

ラベルは、アルファベット文字とアンダースコア(例えばCロケールではA-Za-z0-9_文字が許されます。)の並びです。 ラベルの長さは256バイト未満でなければなりません。

例えば42Personal_Servicesです。

ラベル経路は、例えばL1.L2.L3のようなドットで区切られた0つ以上のラベルの並びであり、階層ツリーのルートから特定のノードまでの経路を表します。 ラベル経路の長さは65キロバイトまでに制限されていますが、2キロバイト以下のサイズがよく使われます。 実際のところこれは主要な制限ではありません。 例えばDMOZカタログ(http://www.dmoz.org)における最大ラベル経路はおよそ240バイトです。

例:'Top.Countries.Europe.Russia'

ltreeモジュールは以下の複数のデータ型を提供します。

注意:ltxtqueryではシンボルの間に空白を入れることができますが、ltreelqueryではできません。

F.15.2. 演算子と関数

ltree型は、通常の比較演算子=<><><=>=を持ちます。 比較では、ツリーの巡回順でソートされ、ノードの子要素はラベルテキストでソートされます。 さらに、以下の特殊な演算子が存在します。

表 F-11. ltree演算子

演算子戻り値説明
ltree @> ltreeboolean左辺の引数が右辺の祖先要素(か同じ)かどうか
ltree <@ ltreeboolean左辺の引数が右辺の子孫要素(か同じ)かどうか
ltree ~ lquerybooleanltreelqueryに一致するかどうか
lquery ~ ltreebooleanltreelqueryに一致するかどうか
ltree ? lquery[]booleanltreeが配列内のいずれかのlqueryに一致するかどうか
lquery[] ? ltreebooleanltreeが配列内のいずれかのlqueryに一致するかどうか
ltree @ ltxtquerybooleanltreeltxtqueryに一致するかどうか
ltxtquery @ ltreebooleanltreeltxtqueryに一致するかどうか
ltree || ltreeltreeltree経路を連結します
ltree || textltreeテキストをltreeに変換し、連結します
text || ltreeltreeテキストをltreeに変換し、連結します
ltree[] @> ltreeboolean配列にltreeの祖先要素が含まれるかどうか
ltree <@ ltree[]boolean配列にltreeの祖先要素が含まれるかどうか
ltree[] <@ ltreeboolean配列にltreeの子孫要素が含まれるかどうか
ltree @> ltree[]boolean配列にltreeの子孫要素が含まれるかどうか
ltree[] ~ lqueryboolean配列にlqueryに一致する経路が含まれるかどうか
lquery ~ ltree[]boolean配列にlqueryに一致する経路が含まれるかどうか
ltree[] ? lquery[]booleanltree配列にいずれかのlqueryに一致する経路が含まれるかどうか
lquery[] ? ltree[]booleanltree配列にいずれかのlqueryに一致する経路が含まれるかどうか
ltree[] @ ltxtqueryboolean配列にltxtqueryに一致する経路が含まれるかどうか
ltxtquery @ ltree[]boolean配列にltxtqueryに一致する経路が含まれるかどうか
ltree[] ?@> ltreeltreeltreeの祖先要素となる配列内の最初の要素。存在しなければNULL
ltree[] ?<@ ltreeltreeltreeの子孫要素となる配列内の最初の要素。存在しなければNULL
ltree[] ?~ lqueryltreelqueryに一致する配列内の最初の要素。存在しなければNULL
ltree[] ?@ ltxtqueryltreeltxtqueryに一致する配列内の最初の要素。存在しなければNULL

<@@>@~演算子は^<@^@>^@^~と類似です。 これらはインデックスを使用しない点を除き、同一です。 これらは試験の際にだけ役に立ちます。

以下の関数が使用可能です。

表 F-12. ltree関数

関数戻り値型説明結果
subltree(ltree, int start, int end)ltreestart位置からend-1位置までのltreeの部分経路(位置は0から始まります)。 subltree('Top.Child1.Child2',1,2)Child1
subpath(ltree, int offset, int len)ltreeoffset位置からlen個のltreeの部分経路(位置は0から始まります)。 offsetが負の場合、部分経路は経路の終端から数えた位置から始まります。 lenが負の場合、経路の終端から指定個のラベルを除きます。 subpath('Top.Child1.Child2',0,2)Top.Child1
subpath(ltree, int offset)ltreeoffset位置から経路の終端までのltreeの部分経路(位置は0から始まります)。 offsetが負の場合、部分経路は経路の終端から数えた位置から始まります。subpath('Top.Child1.Child2',1)Child1.Child2
nlevel(ltree)integer経路内のラベル数nlevel('Top.Child1.Child2')3
index(ltree a, ltree b)integera内でbが最初に出現する位置。存在しなければ-1 index('0.1.2.3.5.4.5.6.8.5.6.8','5.6')6
index(ltree a, ltree b, int offset)integera内でoffsetから検索を始めてbが最初に出現する位置。 負のoffsetは経路終端から-offsetラベルから検索を始めることを意味します。 index('0.1.2.3.5.4.5.6.8.5.6.8','5.6',-4)9
text2ltree(text)ltreetextltreeにキャスト
ltree2text(ltree)textltreetextにキャスト
lca(ltree, ltree, ...)ltree最少共通祖先。つまり、経路で共通する最長接頭辞。(最大8個の引数をサポート) lca('1.2.2.3','1.2.3.4.5.6')1.2
lca(ltree[])ltree最少共通祖先。つまり、経路で共通する最長接頭辞。 lca(array['1.2.2.3'::ltree,'1.2.3'])1.2

F.15.3. インデックス

ltreeは、以下で示された演算子を高速化できる、複数種類のインデックスをサポートします。

F.15.4. 例

この例は、後述のデータを使用します(ソース配布内のcontrib/ltree/ltreetest.sqlファイルでも利用可能です)。

CREATE TABLE test (path ltree);
INSERT INTO test VALUES ('Top');
INSERT INTO test VALUES ('Top.Science');
INSERT INTO test VALUES ('Top.Science.Astronomy');
INSERT INTO test VALUES ('Top.Science.Astronomy.Astrophysics');
INSERT INTO test VALUES ('Top.Science.Astronomy.Cosmology');
INSERT INTO test VALUES ('Top.Hobbies');
INSERT INTO test VALUES ('Top.Hobbies.Amateurs_Astronomy');
INSERT INTO test VALUES ('Top.Collections');
INSERT INTO test VALUES ('Top.Collections.Pictures');
INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy');
INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Stars');
INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Galaxies');
INSERT INTO test VALUES ('Top.Collections.Pictures.Astronomy.Astronauts');
CREATE INDEX path_gist_idx ON test USING gist(path);
CREATE INDEX path_idx ON test USING btree(path);
  

これで、以下の階層を記述するデータが投入されたtestテーブルができます。

                            Top
                         /   |  \
                 Science Hobbies Collections
                     /       |              \
            Astronomy   Amateurs_Astronomy Pictures
               /  \                            |
    Astrophysics  Cosmology                Astronomy
                                            /  |    \
                                     Galaxies Stars Astronauts
  

継承を行うことができます。

ltreetest=# select path from test where path <@ 'Top.Science';
                path
------------------------------------
 Top.Science
 Top.Science.Astronomy
 Top.Science.Astronomy.Astrophysics
 Top.Science.Astronomy.Cosmology
(4 rows)
  

経路一致の例をいくつか示します。

ltreetest=# select path from test where path ~ '*.Astronomy.*';
                     path
-----------------------------------------------
 Top.Science.Astronomy
 Top.Science.Astronomy.Astrophysics
 Top.Science.Astronomy.Cosmology
 Top.Collections.Pictures.Astronomy
 Top.Collections.Pictures.Astronomy.Stars
 Top.Collections.Pictures.Astronomy.Galaxies
 Top.Collections.Pictures.Astronomy.Astronauts
(7 rows)

ltreetest=# select path from test where path ~ '*.!pictures@.*.Astronomy.*';
                path
------------------------------------
 Top.Science.Astronomy
 Top.Science.Astronomy.Astrophysics
 Top.Science.Astronomy.Cosmology
(3 rows)
  

全文検索の例をいくつか示します。

ltreetest=# select path from test where path @ 'Astro*% & !pictures@';
                path
------------------------------------
 Top.Science.Astronomy
 Top.Science.Astronomy.Astrophysics
 Top.Science.Astronomy.Cosmology
 Top.Hobbies.Amateurs_Astronomy
(4 rows)

ltreetest=# select path from test where path @ 'Astro* & !pictures@';
                path
------------------------------------
 Top.Science.Astronomy
 Top.Science.Astronomy.Astrophysics
 Top.Science.Astronomy.Cosmology
(3 rows)
  

関数を使用した経路構築の例です。

ltreetest=# select subpath(path,0,2)||'Space'||subpath(path,2) from test where path <@ 'Top.Science.Astronomy';
                 ?column?
------------------------------------------
 Top.Science.Space.Astronomy
 Top.Science.Space.Astronomy.Astrophysics
 Top.Science.Space.Astronomy.Cosmology
(3 rows)
  

経路内の位置にラベルを挿入するSQL関数を作成することで、これを簡略化することができます。

CREATE FUNCTION ins_label(ltree, int, text) RETURNS ltree
AS 'select subpath($1,0,$2) || $3 || subpath($1,$2);'
LANGUAGE SQL IMMUTABLE;

ltreetest=# select ins_label(path,2,'Space') from test where path <@ 'Top.Science.Astronomy';
                ins_label
------------------------------------------
 Top.Science.Space.Astronomy
 Top.Science.Space.Astronomy.Astrophysics
 Top.Science.Space.Astronomy.Cosmology
(3 rows)
  

F.15.5. 作者

開発はすべてTeodor Sigaev ()とOleg Bartunov ()によりなされました。 さらなる情報についてはhttp://www.sai.msu.su/~megera/postgres/gistを参照してください。 作者は有用な議論を行ったEugeny Rodichevに感謝しています。 コメントや不具合報告を歓迎します。

アダルトレンタルサーバー