Перейти к основному содержимому

ltree. Тип данных для представления меток в иерархической древовидной структуре

В исходном дистрибутиве установлено по умолчанию: нет.

Связанные компоненты: отсутствуют.

Схема размещения: ext.

Модуль реализует типы данных ltree, lquery, ltxtquery и представляет:

  • метки данных в иерархической древовидной структуре;
  • расширенные средства для поиска в таких деревьях.

Примечание:

Метка — это последовательность алфавитно-цифровых символов и знаков подчеркивания длиной до 256 символов. Примеры: 52, Public_Services.

Путь метки — это последовательность из нуля или нескольких разделенных точками меток, представляющая путь от корня иерархического дерева к конкретному узлу. Путь не может содержать больше 65535 меток. Пример: Level1.Level2.Level3.

Модуль предоставляет следующие типы данных:

  1. ltree – путь метки.

  2. lquery – запрос в виде регулярного выражения для поиска нужных значений ltree; в запросе слово выбирает соответствующую метку в заданном пути, а звездочка (*) — ноль или более любых меток.

    • Компоненты запроса можно соединить точками для получения в результате всего пути с указанными метками. Например:
    foo         # Выбирает путь ровно с одной меткой `foo`
    *.foo.* # Выбирает путь, содержащий метку `foo`
    *.foo # Выбирает путь с последней меткой `foo`
    • Для звездочек и слов можно добавить количественное значение, определяющее число меток, которые будут соответствовать этому компоненту. Например:
    *{n}        # Выбирает ровно `n` меток
    *{n,} # Выбирает как минимум `n` меток
    *{n,m} # Выбирает не меньше `n`, но и не более `m` меток
    *{,m} # Выбирает не больше `m` меток — равнозначно `*{0,m}`
    foo{n,m} # Выбирает как минимум `n`, но не больше `m` вхождений `foo`
    foo{,} # Выбирает любое количество вхождений `foo`, в том числе ноль
    • Соответствия при отсутствии явного количественного ограничения:
    Компонент запросаАргументОписание
    *{,}Любое количество меток
    слово{1}Ровно одно вхождение
    • После элемента lquery, кроме *, могут быть добавлены модификаторы, которые позволяют выбрать более сложные условия:
    @           # Выбирает совпадение без учета регистра; например, запросу `a@` соответствует `A`
    * # Выбирает любую метку с заданным префиксом, например, запросу `foo*` соответствует `foobar`
    % # Выбирает в метке начальные слова, разделенные подчеркиваниями

    Модификатор % ищет соответствие по словам, а не по всей метке. Например, запрос foo_bar% выбирает foo_bar_baz, но не foo_barbaz. В сочетании с * сопоставление префикса применяется отдельно к каждому слову, например запрос foo_bar%* выбирает foo1_bar2_baz, но не foo1_br2_baz.

    При перечислении нескольких различных меток, отличных от *, через знак |(ИЛИ), можно выбрать любую из меток. Использованием в начале группы без * знака ! (НЕ), можно обозначить необходимость метки, не соответствующей ни одной из списка. Количественное ограничение, если требуется, задается в конце группы, что означает его действие на группу целиком, ограничивая число меток, соответствующих или не соответствующих приведенным в группе.

  3. ltxtquery – представляет подобный полнотекстовому запрос поиска подходящих значений ltree. Значение ltxtquery содержит слова, возможно с модификаторами @, *, % в конце; эти модификаторы имеют то же значение, что и в lquery. Слова можно объединять символами & (И), | (ИЛИ), ! (НЕ) и скобками. Отличается от lquery тем, что ltxtquery выбирает слова независимо от их положения в пути метки.

Примечание:

ltxtquery допускает пробелы между символами.

ltree, lquery — не допускают пробелы между символами.

Для типа ltree определены простые операторы сравнения:

  • =;
  • <>;
  • <;
  • >;
  • <=;
  • >=.

Сравнение сортирует пути в порядке движения по дереву, а потомки узла сортируются по тексту метки.

Модуль предоставляет специализированные операторы и функции.

Перечень и подробное описание специализированных операторов и функций: https://www.postgresql.org/docs/15/ltree.html#id-1.11.7.32.6

Модуль поддерживает следующие типы индексов для ускорения выполняемых операций:

  1. B-дерево по значениям ltree:

    • <;
    • <=;
    • =;
    • >=;
    • >.
  2. GiST по значениям ltree (класс операторов gist_ltree_ops):

    • <;
    • <=;
    • =;
    • >=;
    • >;
    • @>;
    • <@;
    • @;
    • ~;
    • ?.
  3. GiST-индекс по массиву ltree[] (класс операторов gist_ltree_ops):

    • ltree[] <@ ltree;
    • ltree @> ltree[];
    • @;
    • ~;
    • ?.

Подробное описание индексов ltree: https://www.postgresql.org/docs/15/ltree.html#id-1.11.7.32.7.

Существуют дополнительные расширения, реализующие трансформации типа ltree для языка PL/Python:

Если установить эти трансформации и указать их при создании функции, значения ltree будут отображаться в словаре Python. Обратное преобразование не поддерживается.

Доработка

Доработка не проводилась.

Ограничения

Ограничения отсутствуют.

Установка

Модуль считается «доверенным», поэтому его могут устанавливать пользователи, имеющие право CREATE в текущей базе данных:

CREATE EXTENSION ltree SCHEMA ext;

Внимание!

Расширения, реализующие трансформации, рекомендуется устанавливать в одну схему с ltree. Другая схема может содержать объекты, созданные злонамеренным пользователем. Выбор такой схемы может повлечь за собой угрозу безопасности во время установки расширения.

Настройка

Настройка не требуется.

Использование модуля

Для примера приняты данные из дистрибутива исходного кода – файл contrib/ltree/ltreetest.sql.

Создать таблицу, вставить тестовые данные и создать два индекса:

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

Результат:

                                    Table "ext.test"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
--------+-------+-----------+----------+---------+----------+--------------+-------------
path | ltree | | | | extended | |
Indexes:
"path_gist_idx" gist (path)
"path_idx" btree (path)
Access method: heap

В итоге получатся таблица test c данными, представляющими следующую иерархию:

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

Выбор потомков в иерархии наследования:

SELECT path FROM test WHERE path <@ 'Top.Science';

Пример вывода:

                path                
------------------------------------
Top.Science
Top.Science.Astronomy
Top.Science.Astronomy.Astrophysics
Top.Science.Astronomy.Cosmology
(4 rows)

Примеры выборки по путям:

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)
SELECT path FROM test WHERE path ~ '*.!pictures@.Astronomy.*';

Пример вывода:

                path                
------------------------------------
Top.Science.Astronomy
Top.Science.Astronomy.Astrophysics
Top.Science.Astronomy.Cosmology
(3 rows)

Примеры полнотекстового поиска:

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)
SELECT path FROM test WHERE path @ 'Astro* & !pictures@';

Пример вывода:

                path                
------------------------------------
Top.Science.Astronomy
Top.Science.Astronomy.Astrophysics
Top.Science.Astronomy.Cosmology
(3 rows)

Образование пути с помощью функций:

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;

Использование созданной функции:

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)

Ссылки на документацию разработчика

Дополнительно поставляемый модуль ltree: https://www.postgresql.org/docs/15/ltree.html.