Типы для текстового поиска
QHB предоставляет два типа данных, предназначенных для поддержки полнотекстового поиска. Текстовый поиск — это операция по выполнению поиска в наборе документов на нативном языке с целью обнаружения наиболее соответствующих запросу. Тип tsvector представляет документ в форме, оптимизированной для текстового поиска; тип tsquery аналогичным образом представляет текстовый запрос. Подробное объяснение этого механизма дается в главе Полнотекстовый поиск, а связанные с ним функции и операторы перечислены в разделе Функции и операторы текстового поиска.
tsvector
Значение типа tsvector — это упорядоченный список дискретных лексем, представляющих собой слова, которые были нормализованы для сведения различных вариантов одного и того же слова в один (подробную информацию см. в главе Полнотекстовый поиск). Сортировка и удаление дубликатов выполняются автоматически во время ввода данных, как показано в этом примере:
SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector;
tsvector
----------------------------------------------------
'a' 'and' 'ate' 'cat' 'fat' 'mat' 'on' 'rat' 'sat'
Чтобы представить лексемы, содержащие пробелы или знаки пунктуации, заключите их в апострофы:
SELECT $$the lexeme ' ' contains spaces$$::tsvector;
tsvector
-------------------------------------------
' ' 'contains' 'lexeme' 'spaces' 'the'
(В этом и следующем примерах мы используем строковые литералы, заключенные в двойные знаки доллара, во избежание путаницы из-за необходимости дублировать апострофы внутри литералов). Включаемые апострофы и обратные слэши необходимо продублировать:
SELECT $$the lexeme 'Joe''s' contains a quote$$::tsvector;
tsvector
------------------------------------------------
'Joe''s' 'a' 'contains' 'lexeme' 'quote' 'the'
При необходимости к лексемам можно добавить их целочисленные позиции:
SELECT 'a:1 fat:2 cat:3 sat:4 on:5 a:6 mat:7 and:8 ate:9 a:10 fat:11 rat:12'::tsvector;
tsvector
-------------------------------------------------------------------------------
'a':1,6,10 'and':8 'ate':9 'cat':3 'fat':2,11 'mat':7 'on':5 'rat':12 'sat':4
Позиция обычно указывает местоположение исходного слова в документе. Информацию о положении слова можно использовать для ранжирования близости. Значения позиции могут варьироваться от 1 до 16383; числа выше максимума автоматически устанавливаются на 16383. Дублирующие позиции для одной и той же лексемы отбрасываются.
Лексемы с позициями можно дополнительно пометить весом, который можно выразить буквами A, B, C или D. D является значением по умолчанию и, следовательно, не отображается при выводе:
SELECT 'a:1A fat:2B,4C cat:5D'::tsvector;
tsvector
----------------------------
'a':1A 'cat':5 'fat':2B,4C
Веса, как правило, используются для отражения структуры документа, например, помечая слова заголовка не так, как слова основного текста. Функции ранжирования текстового поиска могут назначать разные приоритеты различным маркерам веса.
Важно понимать, что тип tsvector сам по себе не выполняет нормализацию слов; предполагается, что заданные слова уже соответствующим образом нормализованы для приложения. Например,
SELECT 'The Fat Rats'::tsvector;
tsvector
--------------------
'Fat' 'Rats' 'The'
Для большинства англоязычных приложений для текстового поиска вышеприведенные слова будут считаться ненормализованными, но для типа tsvector это не важно. Обычно для нормализации слов, подходящих для поиска, необработанный текст документа следует пропустить через функцию to_tsvector:
SELECT to_tsvector('english', 'The Fat Rats');
to_tsvector
-----------------
'fat':2 'rat':3
Опять же, более подробную информацию см. в главе Полнотекстовый поиск.
tsquery
Значение tsquery хранит искомые лексемы и может комбинировать их, используя
логические операторы & (И), | (ИЛИ) и ! (НЕ), а также оператор поиска
фразы <-> (ПРЕДШЕСТВУЕТ). Существует также вариант оператора ПРЕДШЕСТВУЕТ вида
<N> , где N — это целочисленная константа, указывающая расстояние между
двумя искомыми лексемами. Запись <-> равнозначна <1>.
Для принудительной группировки этих операторов можно использовать скобки. Без
скобок эти операторы имеют разную степень привязки, в порядке убывания: !
(НЕТ), <-> (ПРЕДШЕСТВУЕТ), & (И) и | (ИЛИ).
Несколько примеров:
SELECT 'fat & rat'::tsquery;
tsquery
---------------
'fat' & 'rat'
SELECT 'fat & (rat | cat)'::tsquery;
tsquery
---------------------------
'fat' & ( 'rat' | 'cat' )
SELECT 'fat & rat & ! cat'::tsquery;
tsquery
------------------------
'fat' & 'rat' & !'cat'
При необходимости лексемы в tsquery можно дополнить одной или несколькими буквами веса, ограничив их сопоставление только теми лексемами tsvector, которые имеют один из этих весов:
SELECT 'fat:ab & cat'::tsquery;
tsquery
------------------
'fat':AB & 'cat'
Кроме того, лексемы в tsquery можно дополнить *, чтобы указать сопоставление по префиксу:
SELECT 'super:*'::tsquery;
tsquery
-----------
'super':*
Этот запрос будет сопоставляться с любым словом в tsvector, которое начинается с «super».
Правила, касающиеся апострофов, для лексем такие же, как описано ранее для лексем в tsvector, и, как и в случае с tsvector, любую необходимую нормализацию слов следует выполнять перед преобразованием в тип tsquery. Для выполнения такой нормализации подходит функция to_tsquery:
SELECT to_tsquery('Fat:ab & Cats');
to_tsquery
------------------
'fat':AB & 'cat'
Обратите внимание, что to_tsquery будет обрабатывать префиксы так же, как и другие слова, поэтому это сравнение возвращает true:
SELECT to_tsvector( 'postgraduate' ) @@ to_tsquery( 'postgres:*' );
?column?
----------
t
потому что postgres усекается до postgr:
SELECT to_tsvector( 'postgraduate' ), to_tsquery( 'postgres:*' );
to_tsvector | to_tsquery
---------------+------------
'postgradu':1 | 'postgr':*
что будет соответствовать усеченной форме postgraduate.