Подтвердить что ты не робот

"to_tsquery" на tsvector дает разные результаты при использовании "простых" и "английских"?

Я был привлечен к участию в проекте, и я возвращаюсь в PostgreSQL после того, как не работал с ним несколько лет. Отсутствие использования в стороне, я никогда не сталкивался с использованием полей tsvector раньше и теперь обнаруживаю, что сталкиваюсь с ошибкой, основанной на них. Я прочитал документацию по типу поля и ее цель, но мне сложно перекопать документацию о том, как "простой" отличается от "english" как первый параметр to_tsquery()

Пример

> SELECT to_tsvector('mortgag') @@ to_tsquery('simple', 'mortgage')
?column? 
----------
 f
(1 row)

> SELECT to_tsvector('mortgag') @@ to_tsquery('english', 'mortgage')
?column? 
----------
 t
(1 row)

Я бы подумал, что оба они вернут true, но, очевидно, первое не делает - почему?

4b9b3361

Ответ 1

FTS использует dictionaries для нормализации текста:

12,6. Словари

Словари используются для устранения слов, которые не следует рассматривать в поиске (стоп-слова), и нормализовать слова, чтобы соответствовали разные производные формы одного и того же слова. Успешно нормализованное слово называется лексемой.

Так словари используются, чтобы выкидывать вещи, которые слишком распространены или бессмысленны для поиска в поиске (остановить слова) и нормализовать все остальное, чтобы город и города, например, соответствовали бы, даже если это разные слова.

Посмотрим на какой-то вывод из ts_debug и посмотрим, что происходит с словарями:

=> select * from ts_debug('english', 'mortgage');
   alias   |   description   |  token   |  dictionaries  |  dictionary  |  lexemes  
-----------+-----------------+----------+----------------+--------------+-----------
 asciiword | Word, all ASCII | mortgage | {english_stem} | english_stem | {mortgag}

=> select * from ts_debug('simple', 'mortgage');
   alias   |   description   |  token   | dictionaries | dictionary |  lexemes   
-----------+-----------------+----------+--------------+------------+------------
 asciiword | Word, all ASCII | mortgage | {simple}     | simple     | {mortgage}

Обратите внимание, что simple использует словарь simple, тогда как english использует словарь english_stem.

simple словарь:

работает путем преобразования входного токена в нижний регистр и проверки его на файл стоп-слов. Если он найден в файле, возвращается пустой массив, в результате чего маркер будет отброшен. Если нет, нижняя обложка формы возвращается как нормализованная лексема.

Словарь simple просто выкидывает стоп-слова, ошибки и об этом. Мы сами видим его простоту:

=> select to_tsquery('simple', 'Mortgage'), to_tsquery('simple', 'Mortgages');
 to_tsquery | to_tsquery  
------------+-------------
 'mortgage' | 'mortgages'

Словарь simple слишком прост, чтобы даже обрабатывать простые множественные числа.

Итак, что же это за словарь english_stem? Суффикс "stem" - это раздача: этот словарь применяет алгоритм создания слов для преобразования (например) города и городов в одно и то же. Из точное руководство:

12.6.6. Словарь снежного кома

Шаблон словаря Snowball основан на проекте Мартина Портера, изобретателя популярного алгоритма String для английского языка. [...] Каждый алгоритм понимает, как сводить общие вариантные формы слов к базе или стержню, написание в пределах своего языка.

И чуть ниже этого мы видим словарь english_stem:

CREATE TEXT SEARCH DICTIONARY english_stem (
    TEMPLATE = snowball,
    Language = english,
    StopWords = english
);

Итак, словарь english_stem содержит слова, и мы можем видеть, что это происходит:

=> select to_tsquery('english', 'Mortgage'), to_tsquery('english', 'Mortgages');
 to_tsquery | to_tsquery 
------------+------------
 'mortgag'  | 'mortgag'

Резюме: 'simple' подразумевает простое сопоставление литералов, 'english' применяется к тому, чтобы (надеюсь) добиться лучшего соответствия. Пресечение превращает ипотеку в ипотеку, и это дает вам ваш матч.