pg_trgm

Определение схожести алфавитно-цифровых строк на основе триграмм.
Схема размещения: ext.
Модуль pg_trgm предоставляет:
  • функции и операторы для определения схожести алфавитно-цифровых строк на основе триграмм;
  • классы операторов индексов, поддерживающие быстрый поиск схожих строк.
Триграмма — это группа трех взятых из строки последовательных символов. Сопоставление количества триграмм в двух строках позволяет оценить их схожесть и активно применяется во многих языках.
Функции:
ИмяВходные переменные функцииВыходные переменные функцииОписание
similarity
text, textrealВозвращает число, показывающее, насколько близки два аргумента. Диапазон результатов — от 0 (две строки полностью различны) до 1 (две строки идентичны)
show_trgm
texttext[]Возвращает массив всех триграмм в заданной строке
word_similarity
text, textrealВозвращает число, представляющее наибольшую степень схожести между набором триграмм в первой строке и любым непрерывным фрагментом упорядоченного набора триграмм во второй строке
strict_word_similarity
text, textrealПодобна word_similarity, но подгоняет границы фрагментов к границам слов. Так как триграммы не пересекают слова, эта функция фактически выдает наибольшую степень схожести между первой строкой и любой непрерывной последовательностью слов во второй строке
show_limit
realВозвращает текущий порог схожести, который использует оператор %. Это значение задает минимальную схожесть между двумя словами, при которой они считаются настолько близкими, что одно может быть, например, ошибочным написанием другого.
Устаревшая функция; используйте SHOW pg_trgm.similarity_threshold
set_limit
realrealЗадает текущий порог схожести, который использует оператор %. Это значение должно быть в диапазоне от 0 до 1 (по умолчанию 0.3). Возвращает то же значение, что было передано на вход.
Устаревшая функция; используйте SET pg_trgm.similarity_threshold
Операторы:
ИмяВыходные переменныеОписание
text % text
booleanОпределяет схожесть аргументов относительно текущего порога, заданного параметром pg_trgm.similarity_threshold;
true – схожесть аргументов выше уровня текущего порога
text <% text
booleanОпределяет схожесть набора триграмм в первом аргументе и непрерывного фрагмента упорядоченного набора триграмм во втором относительно уровня схожести, установленного в параметре pg_trgm.word_similarity_threshold
true – если схожесть выше уровня порога
text %> text
booleanКоммутирующий оператор для <%
text <<% text
booleanВозвращает true, если во втором аргументе имеется непрерывный фрагмент упорядоченного набора триграмм, соответствующий границам слов, и его схожесть с набором триграмм первого аргумента превышает уровень схожести, установленный параметром pg_trgm.strict_word_similarity_threshold
text %>> text
booleanКоммутирующий оператор для <<%
text <-> text
realВозвращает «расстояние» между аргументами, выражаемое как разность единицы и значения similarity()
text <<-> text
realВозвращает «расстояние» между аргументами, выраженное как разность единицы и значения word_similarity()
text <->> text
realКоммутирующий оператор для <<->
text <<<-> text
realВозвращает «расстояние» между аргументами, выраженное как разность единицы и значения strict_word_similarity()
text <->>> text
realКоммутирующий оператор для <<<->
Параметры GUC:
ИмяАргументНазначениеИспользуется операторомДиапазонЗначение по умолчанию
pg_trgm.similarity_threshold
realТекущий порог схожести%0 – 10.3
pg_trgm.word_similarity_threshold
realТекущий порог схожести слов<% и %>0 – 10.6
pg_trgm.strict_word_similarity_threshold
realТекущий порог схожести строго слов<<% и %>>0 – 10.5
Поддержка индексов:
Модуль pg_trgm предоставляет классы операторов индексов GiST и GIN, позволяющие создавать индекс по текстовым столбцам для быстрого поиска по критерию схожести.
Типы индексов GiST и GIN поддерживают вышеописанные операторы схожести и дополнительно поддерживают поиск на основе триграмм для запросов: LIKE, ILIKE, ~, ~*.
Индексы GiST и GIN не поддерживают простые операторы сравнения и равенства, поэтому может понадобиться индекс на основе B-дерева.
CREATE TABLE test_trgm (t text);
CREATE INDEX trgm_idx ON test_trgm USING GIST (t gist_trgm_ops);
Раскрыть type=sql
                                 Table "ext.test_trgm"
 Column | Type | Collation | Nullable | Default | Storage  | Stats target | Description
--------+------+-----------+----------+---------+----------+--------------+-------------
 t      | text |           |          |         | extended |              |
Indexes:
    "trgm_idx" gist (t gist_trgm_ops)
Access method: heap
Класс операторов GiST gist_trgm_ops аппроксимирует набор триграмм в виде сигнатуры битовой карты. В его необязательном целочисленном параметре siglen можно задать размер сигнатуры в байтах.
Параметр может принимать значения от 1 до 2024, по умолчанию равен 12.
При увеличении размера сигнатуры поиск работает точнее, потому что сканируется меньшая область в индексе и меньше страниц кучи, однако сам индекс становится больше.
Пример создания такого индекса с длиной сигнатуры 32 байта:
CREATE INDEX trgm_idxs ON test_trgm USING GIST (t gist_trgm_ops(siglen=32));
Раскрыть type=sql
                                 Table "ext.test_trgm"
 Column | Type | Collation | Nullable | Default | Storage  | Stats target | Description
--------+------+-----------+----------+---------+----------+--------------+-------------
 t      | text |           |          |         | extended |              |
Indexes:
    "trgm_idx" gist (t gist_trgm_ops)
    "trgm_idxs" gist (t gist_trgm_ops (siglen='32'))
Access method: heap
Используя индекс по столбцу t, можно осуществлять поиск по схожести:
SELECT t, similarity (t, 'first') AS sml
  FROM test_trgm
  WHERE t % 'fir'
  ORDER BY sml DESC, t;
В текстовом столбце будут выданы все схожие с интересующим словом значения. Порядок сортировки – от наиболее к наименее схожим. С использованием индекса эта операция будет быстрой даже с очень большими наборами данных.
Раскрыть type=sql
   t   |    sml
-------+------------
 first |          1
 fire  |      0.375
 fires | 0.33333334
 fi    |  0.2857143
(4 rows)
Другой вариант предыдущего запроса (может быть эффективно выполнен с применением индексов GiST) выигрышнее первого варианта только тогда, когда требуется получить небольшое количество близких совпадений:
SELECT t, t <-> 'fir' AS dist
  FROM test_trgm
  ORDER BY dist LIMIT 10;
Результат выполнения запроса:
Раскрыть type=sql
   t    |    dist
--------+------------
 fire   |        0.5
 first  | 0.57142854
 fires  | 0.57142854
 fi     |        0.6
 th     |          1
 third  |          1
 second |          1
 tyres  |          1
 second |          1
(9 rows)
Можно использовать индекс по столбцу t для строгой и нестрогой оценки схожести слов.
Примеры типичных запросов:
SELECT t, word_similarity('fir', t) AS sml
  FROM test_trgm
  WHERE 'fir' <% t
  ORDER BY sml DESC, t;
Результат выполнения запроса:
Раскрыть type=sql
   t   | sml
-------+------
 fire  | 0.75
 fires | 0.75
 first | 0.75
 first | 0.75
(4 rows)
или
SELECT t, strict_word_similarity('fir', t) AS sml
  FROM test_trgm
  WHERE 'fir' <<% t
  ORDER BY sml DESC, t;
Результат выполнения запроса:
Раскрыть type=sql
  t   | sml
------+-----
 fire | 0.5
(1 row)
В результате возвращены все значения текстового столбца, для которых в упорядоченном наборе триграмм найдется непрерывный фрагмент, достаточно схожий с набором триграмм строки fir.
Типы индексов GiST и GIN также поддерживают поиск:
  • с операторами LIKE и ILIKE, например:
    SELECT * FROM test_trgm WHERE t LIKE '%fir%tyr';
    При таком поиске по индексу сначала из искомой строки извлекаются триграммы, а затем они ищутся в индексе. Чем больше триграмм оказывается в искомой строке, тем более эффективным будет поиск по индексу. В отличие от поиска по B-дереву, искомая строка не должна привязываться к левому краю.
    Результат выполнения запроса:
    Раскрыть type=sql
     t
    ---
    (0 rows)
    
  • по регулярным выражениям (операторы ~ и ~*), например:
    SELECT * FROM test_trgm WHERE t ~ '(fir|tyr)';
    При таком поиске из регулярного выражения извлекаются триграммы, а затем они ищутся в индексе. Чем больше триграмм удается извлечь из регулярного выражения, тем более эффективным будет поиск по индексу. В отличие от поиска по B-дереву, искомая строка не должна привязываться к левому краю.
    Результат выполнения запроса:
    Раскрыть type=sql
     t
    -------
     first
     fire
     fires
     tyres
    (4 rows)
    
При отсутствии триграмм в искомом шаблоне, поиск сводится к полному сканированию индекса.
Интеграция с текстовым поиском
Сопоставление триграмм — очень полезный прием в сочетании с применением полнотекстового индекса. Это может помочь найти слова, написанные неправильно, которые не будут находиться непосредственно механизмом полнотекстового поиска.
Для возможности поиска нужно:
  • построить дополнительную таблицу, содержащую все уникальные слова в документе:
    CREATE TABLE words AS SELECT word FROM
            ts_stat('SELECT to_tsvector(''simple'', bodytext) FROM documents');
    
    где:
    • documents — это таблица с текстовым полем bodytext, по которому будет выполняться поиск;
    • simple – конфигурация используется с функцией to_tsvector вместо конфигурации для определенного языка по причине того, что нам нужен список исходных (необработанных стеммером) слов.
  • создать индекс триграмм по столбцу со словами:
    CREATE INDEX words_idx ON words USING GIN (word gin_trgm_ops);
После создания таблицы и индекса можно использовать запрос SELECT, подобный показанному в предыдущем примере, и предлагать варианты исправлений слов, введенных пользователем с ошибками. Для улучшения результата можно дополнительно проверить, что выбранные слова имеют длину, примерно равную длинам ошибочных слов.

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

  1. Функция similarity:
    SELECT similarity ('Pangolin','Postgres');
    Пример результата запроса:
    Раскрыть type=sql
     similarity
    ------------
     0.05882353
    (1 row)
    
    Другой пример:
    SELECT similarity ('cat','cate');
    Пример результата запроса:
    Раскрыть type=sql
     similarity
    ------------
            0.5
    (1 row)
    
  2. Функция show_trgm:
    SELECT show_trgm ('Pangolin');
    Пример результата запроса:
    Раскрыть type=sql
                      show_trgm
    ---------------------------------------------
     {"  p"," pa",ang,gol,"in ",lin,ngo,oli,pan}
    (1 row)
    
  3. Функция word_similarity:
    SELECT word_similarity ('Pangolin','Mango');
    Пример результата запроса:
    Раскрыть type=sql
     word_similarity
    -----------------
          0.22222222
    (1 row)
    
  4. Функция strict_word_similarity:
    SELECT strict_word_similarity ('Pangolin','Mango');
    Пример результата запроса:
    Раскрыть type=sql
     strict_word_similarity
    ------------------------
                 0.15384616
    (1 row)
    

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

Дополнительную информацию по поставляемому модулю pg_trgm можно получить по ссылке.
Предыдущий раздел
pgstattuple
Следующий раздел
pg_variables
Была ли страница полезной?