12.6. Словари#
12.6. Словари #
Все словари используются для исключения слов, которые не должны учитываться при поиске (стоп-слова), а также для нормализации слов, чтобы различные производные формы одного и того же слова совпадали. Успешно нормализованное слово называется лексемой. Помимо улучшения качества поиска, нормализация и удаление стоп-слов уменьшают размер представления документа в виде tsvector
, что улучшает производительность. Нормализация не всегда имеет лингвистическое значение и обычно зависит от семантики приложения.
Некоторые примеры нормализации:
Лингвистические — словари Ispell пытаются привести входные слова к нормализованной форме; словари стеммера удаляют окончания слова
Местоположения URL могут быть канонизированы, чтобы сделать эквивалентные URL-адреса совпадающими:
http://www.pgsql.ru/db/mw/index.html
http://www.pgsql.ru/db/mw/
http://www.pgsql.ru/db/../db/mw/index.html
Имена цветов могут быть заменены их шестнадцатеричными значениями, например,
red, green, blue, magenta -> FF0000, 00FF00, 0000FF, FF00FF
Если индексируются числа, можно удалить некоторое количество десятичных знаков, чтобы уменьшить диапазон возможных чисел, так что, например, 3.14159265359, 3.1415926, 3.14 будут одинаковыми после нормализации, если после десятичной точки оставить только две цифры.
Словарь - это программа, которая принимает компонент в качестве входных данных и возвращает:
массив лексем, если входной компонент известен словарю (обратите внимание, что один компонент может порождать более одной лексемы)
один отдельный лексем с установленным флагом
TSL_FILTER
, чтобы заменить исходный компонент новым компонентом, который будет передан последующим словарям (словарь, выполняющий это, называется фильтрующим словарем)пустой массив, если словарь знает компонент, но это стоп-слово
NULL
если словарь не распознает входной компонент
Tantor BE предоставляет предопределенные словари для многих языков. Также есть несколько предопределенных шаблонов, которые можно использовать для создания новых словарей с настраиваемыми параметрами. Каждый предопределенный шаблон словаря описан ниже. Если ни один из существующих шаблонов не подходит, можно создать новые; см. раздел contrib/
в дистрибутиве Tantor BE для примеров.
Конфигурация полнотекстового поиска связывает парсер с набором словарей для обработки выходных компонентов парсера. Для каждого типа компонента, который может вернуть парсер, конфигурацией указывается отдельный список словарей. Когда парсер находит компонент этого типа, каждый словарь в списке проверяется по очереди, пока какой-то словарь не распознает его как известное слово. Если компонент идентифицируется как стоп-слово или если ни один словарь не распознает компонент, он будет отброшен и не будет проиндексирован или использован для поиска.
Обычно первый словарь, который возвращает не-NULL
результат, определяет результат, и остальные словари не проверяются; но фильтрующий словарь может заменить заданное слово на измененное слово, которое затем передается последующим словарям.
Общее правило для настройки списка словарей заключается в том, чтобы сначала разместить самый узкий, наиболее специфический словарь, затем более общие словари, заканчивая очень общим словарем, таким как стеммер Snowball или simple
, который распознает все. Например, для поиска, связанного с астрономией (astro_en
конфигурация), можно привязать тип компонента asciiword
(ASCII-слово) к синонимическому словарю астрономических терминов, общему английскому словарю и английскому стеммеру Snowball:
ALTER TEXT SEARCH CONFIGURATION astro_en ADD MAPPING FOR asciiword WITH astrosyn, english_ispell, english_stem;
Словарь фильтрации может быть размещен в любом месте списка, кроме конца, где он был бы бесполезен. Словари фильтрации полезны для частичной нормализации слов, чтобы упростить задачу последующих словарей. Например, словарь фильтрации может использоваться для удаления ударений с ударных букв, как это делает модуль unaccent.
12.6.1. Стоп-слова #
Стоп-слова - это слова, которые очень часто встречаются в почти каждом документе и не имеют дискриминационной ценности. Поэтому их можно игнорировать в контексте полнотекстового поиска. Например, в каждом английском тексте содержатся слова, такие как a
и the
, поэтому их хранение в индексе бесполезно. Однако стоп-слова влияют на позиции в tsvector
, что, в свою очередь, влияет на ранжирование:
SELECT to_tsvector('english', 'in the list of stop words'); to_tsvector ---------------------------- 'list':3 'stop':5 'word':6
Отсутствующие позиции 1, 2, 4 обусловлены стоп-словами. Ранги, рассчитанные для документов с и без стоп-слов, существенно отличаются:
SELECT ts_rank_cd (to_tsvector('english', 'in the list of stop words'), to_tsquery('list & stop')); ts_rank_cd ------------ 0.05 SELECT ts_rank_cd (to_tsvector('english', 'list stop words'), to_tsquery('list & stop')); ts_rank_cd ------------ 0.1
Все зависит от конкретного словаря, как он обрабатывает стоп-слова. Например, словари ispell
сначала нормализуют слова, а затем проверяют список стоп-слов, в то время как стеммеры Snowball
сначала проверяют список стоп-слов. Причина различного поведения заключается в попытке уменьшить шум.
12.6.2. Простой Словарь #
Шаблон simple
словаря работает путем преобразования входного компонента в нижний регистр и проверки его по файлу стоп-слов. Если компонент найден в файле, то возвращается пустой массив, что приводит к отбрасыванию компонента. Если же компонент не найден, то возвращается нормализованная лексема в нижнем регистре. В качестве альтернативы, словарь может быть настроен на отображение нераспознанных слов, не являющихся стоп-словами, что позволяет передавать их следующему словарю в списке.
Вот пример определения словаря, использующего шаблон simple
:
CREATE TEXT SEARCH DICTIONARY public.simple_dict ( TEMPLATE = pg_catalog.simple, STOPWORDS = english );
Здесь english
- это базовое имя файла стоп-слов.
Полное имя файла будет $SHAREDIR/tsearch_data/english.stop
,
где $SHAREDIR
означает общий каталог данных установки
Tantor BE, часто /usr/local/share/postgresql
(используйте pg_config --sharedir
, чтобы определить его, если вы не уверены).
Формат файла просто представляет собой список слов, по одному на строку.
Пустые строки и конечные пробелы игнорируются,
и прописные буквы преобразуются в строчные, но никакой другой обработки содержимого файла не выполняется.
Теперь можно протестировать наш словарь:
SELECT ts_lexize('public.simple_dict', 'YeS'); ts_lexize ----------- {yes} SELECT ts_lexize('public.simple_dict', 'The'); ts_lexize ----------- {}
Мы также можем выбрать возвращать NULL
, вместо слова в нижнем регистре, если оно не найдено в файле стоп-слов. Это поведение выбирается путем установки параметра Accept
словаря в значение false
. Продолжая пример:
ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false ); SELECT ts_lexize('public.simple_dict', 'YeS'); ts_lexize ----------- SELECT ts_lexize('public.simple_dict', 'The'); ts_lexize ----------- {}
С сохранением настроек по умолчанию Accept
= true
имеет смысл размещать только simple
словарь в конце списка словарей, поскольку он никогда не передаст компонент следующему словарю. Напротив, Accept
= false
имеет смысл только при наличии хотя бы одного следующего словаря.
Предостережение
Большинство типов словарей полагается на файлы конфигурации, такие как файлы стоп-слов. Эти файлы должны быть сохранены в кодировке UTF-8. Они будут преобразованы в фактическую кодировку базы данных, если она отличается, при их чтении на сервере.
Предостережение
Обычно сессия базы данных считывает файл конфигурации словаря только один раз, когда он впервые используется в сессии. Если вы измените файл конфигурации и хотите, чтобы существующие сессии получили новое содержимое, выполните команду ALTER TEXT SEARCH DICTIONARY
на словаре. Это может быть “фиктивное” обновление, которое фактически не изменяет значения параметров.
12.6.3. Словарь синонимов #
Этот шаблон словаря используется для создания словарей, заменяющих слово синонимом. Фразы не поддерживаются (для этого используйте шаблон тезауруса (Раздел 12.6.4). Синонимический словарь может использоваться для преодоления лингвистических проблем, например, чтобы предотвратить сокращение слова “Paris” до “pari” в английском словаре стеммера. Достаточно иметь строку Paris paris
в синонимическом словаре и поместить ее перед словарем english_stem
. Например:
SELECT * FROM ts_debug('english', 'Paris'); alias | description | token | dictionaries | dictionary | lexemes -----------+-----------------+-------+----------------+--------------+--------- asciiword | Word, all ASCII | Paris | {english_stem} | english_stem | {pari} CREATE TEXT SEARCH DICTIONARY my_synonym ( TEMPLATE = synonym, SYNONYMS = my_synonyms ); ALTER TEXT SEARCH CONFIGURATION english ALTER MAPPING FOR asciiword WITH my_synonym, english_stem; SELECT * FROM ts_debug('english', 'Paris'); alias | description | token | dictionaries | dictionary | lexemes -----------+-----------------+-------+---------------------------+------------+--------- asciiword | Word, all ASCII | Paris | {my_synonym,english_stem} | my_synonym | {paris}
Единственным параметром, требуемым шаблоном synonym
, является
SYNONYMS
, который является базовым именем его конфигурационного файла
— my_synonyms
в приведенном выше примере.
Полное имя файла будет
$SHAREDIR/tsearch_data/my_synonyms.syn
(где $SHAREDIR
означает
общий каталог данных установки Tantor BE).
Формат файла состоит из одной строки
на каждое слово, которое должно быть заменено, с последующим синонимом,
разделенными пробелом. Пустые строки и конечные пробелы игнорируются.
Шаблон synonym
также имеет необязательный параметр CaseSensitive
, который по умолчанию установлен в false
. Когда CaseSensitive
равно false
, слова в файле синонимов приводятся к нижнему регистру, а также вводимые компоненты. Когда он равен true
, слова и компоненты не приводятся к нижнему регистру, но сравниваются как есть.
Звездочка (*
) может быть помещена в конце синонима в файле конфигурации. Это указывает на то, что синоним является префиксом. Звездочка игнорируется при использовании записи в to_tsvector()
, но когда она используется в to_tsquery()
, результатом будет элемент запроса с маркером совпадения префикса (см. Раздел 12.3.2). Например, предположим, что у нас есть следующие записи в $SHAREDIR/tsearch_data/synonym_sample.syn
:
postgres pgsql postgresql pgsql postgre pgsql gogle googl indices index*
Затем мы получим следующие результаты:
mydb=# CREATE TEXT SEARCH DICTIONARY syn (template=synonym, synonyms='synonym_sample'); mydb=# SELECT ts_lexize('syn', 'indices'); ts_lexize ----------- {index} (1 row) mydb=# CREATE TEXT SEARCH CONFIGURATION tst (copy=simple); mydb=# ALTER TEXT SEARCH CONFIGURATION tst ALTER MAPPING FOR asciiword WITH syn; mydb=# SELECT to_tsvector('tst', 'indices'); to_tsvector ------------- 'index':1 (1 row) mydb=# SELECT to_tsquery('tst', 'indices'); to_tsquery ------------ 'index':* (1 row) mydb=# SELECT 'indexes are very useful'::tsvector; tsvector --------------------------------- 'are' 'indexes' 'useful' 'very' (1 row) mydb=# SELECT 'indexes are very useful'::tsvector @@ to_tsquery('tst', 'indices'); ?column? ---------- t (1 row)
12.6.4. Тезаурус Словарь #
Словарь тезауруса (иногда сокращенно называемый TZ) - это сборник слов, который содержит информацию о взаимосвязях слов и фраз, таких как более общие термины (BT), более узкие термины (NT), предпочтительные термины, непредпочтительные термины, связанные термины и т. д.
В основном, тезаурусный словарь заменяет все непредпочтительные термины одним предпочтительным термином и, по желанию, сохраняет исходные термины для индексации. Текущая реализация тезаурусного словаря в Tantor BE является расширением синонимического словаря с добавленной поддержкой фраз. Для тезаурусного словаря требуется файл конфигурации следующего формата:
# this is a comment sample word(s) : indexed word(s) more sample word(s) : more indexed word(s) ...
где символ двоеточия (:
) действует как разделитель между фразой и ее заменой.
Словарь тезауруса использует подсловарь (который
указывается в конфигурации словаря) для нормализации входного
текста перед проверкой на соответствие фраз. Возможно выбрать только один
подсловарь. Если подсловарь не распознает слово, будет выдана ошибка.
В этом случае вы должны удалить использование этого слова или
обучить подсловарь его распознаванию. Вы можете поставить звездочку
(*
) в начале индексированного слова, чтобы пропустить
его обработку подсловарем, но все примеры слов должны быть известны
подсловарю.
Словарь тезауруса выбирает самое длинное совпадение, если есть несколько фраз, соответствующих вводу, и разрешает противоречия, используя последнее определение.
Определенные стоп-слова, распознаваемые подсловарем, нельзя указать; вместо этого используйте ?
для обозначения места, где может появиться любое стоп-слово. Например, предположим, что a
и the
являются стоп-словами согласно подсловарю:
? one ? two : swsw
соответствует a one the two
и the one a two
;
оба будут заменены на swsw
.
Так как тезаурусный словарь имеет возможность распознавать фразы, он должен запоминать свое состояние и взаимодействовать с парсером. Тезаурусный словарь использует эти присваивания, чтобы проверить, должен ли он обрабатывать следующее слово или прекратить накопление. Тезаурусный словарь должен быть настроен тщательно. Например, если тезаурусный словарь назначен для обработки только компонента asciiword
, то определение тезаурусного словаря вида one 7
не будет работать, так как тип компонента uint
не назначен для тезаурусного словаря.
Предостережение
Тезаурусы используются во время индексации, поэтому любое изменение параметров словаря тезауруса требует повторной индексации. Для большинства других типов словарей небольшие изменения, такие как добавление или удаление стоп-слов, не приводят к принудительной повторной индексации.
12.6.4.1. Конфигурация тезауруса #
Для определения нового словаря тезауруса используйте шаблон thesaurus
.
Например:
CREATE TEXT SEARCH DICTIONARY thesaurus_simple ( TEMPLATE = thesaurus, DictFile = mythesaurus, Dictionary = pg_catalog.english_stem );
Здесь:
thesaurus_simple
- это имя нового словаря.mythesaurus
- это базовое имя файла конфигурации тезауруса. (Полное имя файла будет$SHAREDIR/tsearch_data/mythesaurus.ths
, где$SHAREDIR
означает общий каталог установки данных).pg_catalog.english_stem
- это подсловарь (здесь используется английский стеммер Snowball) для использования нормализации тезауруса. Обратите внимание, что у подсловаря будет своя собственная конфигурация (например, стоп-слова), которая здесь не показана.
Теперь возможно привязать словарь тезауруса thesaurus_simple
к желаемым типам компонентов в конфигурации, например:
ALTER TEXT SEARCH CONFIGURATION russian ALTER MAPPING FOR asciiword, asciihword, hword_asciipart WITH thesaurus_simple;
12.6.4.2. Пример тезауруса #
Рассмотрим простой астрономический тезаурус thesaurus_astro
,
который содержит некоторые астрономические словосочетания:
supernovae stars : sn crab nebulae : crab
Ниже мы создаем словарь и связываем некоторые типы компонентов с астрономическим тезаурусом и английским стеммером:
CREATE TEXT SEARCH DICTIONARY thesaurus_astro ( TEMPLATE = thesaurus, DictFile = thesaurus_astro, Dictionary = english_stem ); ALTER TEXT SEARCH CONFIGURATION russian ALTER MAPPING FOR asciiword, asciihword, hword_asciipart WITH thesaurus_astro, english_stem;
Теперь можно увидеть, как это работает.
ts_lexize
не очень полезна для тестирования тезауруса,
потому что она рассматривает входные данные как один компонент. Вместо этого можно использовать
plainto_tsquery
и to_tsvector
,
которые разобьют входные строки на несколько компонентов:
SELECT plainto_tsquery('supernova star'); plainto_tsquery ----------------- 'sn' SELECT to_tsvector('supernova star'); to_tsvector ------------- 'sn':1
В принципе, можно использовать to_tsquery
, если заключить аргумент в кавычки:
SELECT to_tsquery('''supernova star'''); to_tsquery ------------ 'sn'
Обратите внимание, что supernova star
соответствует supernovae
stars
в thesaurus_astro
, потому что мы указали
стеммер english_stem
в определении тезауруса.
Стеммер удалил e
и s
.
Чтобы проиндексировать исходную фразу, а также ее замену, просто включите ее в правую часть определения:
supernovae stars : sn supernovae stars SELECT plainto_tsquery('supernova star'); plainto_tsquery ----------------------------- 'sn' & 'supernova' & 'star'
12.6.5. Ispell Словарь #
Словарный шаблон Ispell поддерживает морфологические словари, которые могут нормализовать множество различных лингвистических форм слова в один и тот же лексем. Например, английский словарь Ispell может сопоставить все склонения и спряжения искомого термина bank
, например, banking
, banked
, banks
, banks'
и bank's
.
Стандартное распространение Tantor BE не включает в себя файлы конфигурации Ispell. Словари для большого числа языков доступны на сайте Ispell. Также поддерживаются некоторые более современные форматы файлов словарей — MySpell (OO < 2.0.1) и Hunspell (OO >= 2.0.2). Большой список словарей доступен на вики-странице OpenOffice.
Для создания словаря Ispell выполните следующие шаги:
Скачайте файлы конфигурации словаря. Файлы расширения OpenOffice имеют расширение
.oxt
. Необходимо извлечь файлы.aff
и.dic
, изменить расширения на.affix
и.dict
. Для некоторых словарей также требуется преобразование символов в кодировку UTF-8 с помощью команд (например, для словаря на норвежском языке).iconv -f ISO_8859-1 -t UTF-8 -o nn_no.affix nn_NO.aff iconv -f ISO_8859-1 -t UTF-8 -o nn_no.dict nn_NO.dic
Скопируйте файлы в каталог
$SHAREDIR/tsearch_data
.загрузите файлы в PostgreSQL с помощью следующей команды:
CREATE TEXT SEARCH DICTIONARY english_hunspell ( TEMPLATE = ispell, DictFile = en_us, AffFile = en_us, Stopwords = english);
Здесь, DictFile
, AffFile
и StopWords
указываются базовые имена файлов словаря, аффиксов и стоп-слов.
Файл стоп-слов имеет тот же формат, о котором говорилось выше для
типа словаря simple
. Формат других файлов
не указан здесь, но доступен на указанных выше веб-сайтах.
Ispell словари обычно распознают ограниченный набор слов, поэтому они должны быть дополнены другим более широким словарем; например, словарем Snowball, который распознает все.
Файл .affix
приложения Ispell имеет следующую структуру:
prefixes flag *A: . > RE # As in enter > reenter suffixes flag T: E > ST # As in late > latest [^AEIOU]Y > -Y,IEST # As in dirty > dirtiest [AEIOU]Y > EST # As in gray > grayest [^EY] > EST # As in small > smallest
И файл .dict
имеет следующую структуру:
lapse/ADGRS lard/DGRS large/PRTY lark/MRS
Формат файла .dict
следующий:
basic_form/affix_class_name
В файле .affix
каждый флаг аффикса описывается в следующем формате:
condition > [-stripping_letters,] adding_affix
Здесь условие имеет формат, аналогичный формату регулярных выражений.
Оно может использовать группировки [...]
и [^...]
.
Например, [AEIOU]Y
означает, что последняя буква слова
это "y"
, а предпоследняя буква - "a"
,
"e"
, "i"
, "o"
или "u"
.
[^EY]
означает, что последняя буква не является ни "e"
,
ни "y"
.
Поддержка словарей Ispell разделения сложных слов; полезная функция.
Обратите внимание, что файл аффиксов должен указывать специальный флаг с использованием оператора compoundwords controlled
, который помечает слова словаря, которые могут участвовать в образовании сложных слов:
compoundwords controlled z
Вот несколько примеров для норвежского языка:
SELECT ts_lexize('norwegian_ispell', 'overbuljongterningpakkmesterassistent'); {over,buljong,terning,pakk,mester,assistent} SELECT ts_lexize('norwegian_ispell', 'sjokoladefabrikk'); {sjokoladefabrikk,sjokolade,fabrikk}
MySpell формат является подмножеством Hunspell.
Файл .affix
Hunspell имеет следующую
структуру:
PFX A Y 1 PFX A 0 re . SFX T N 4 SFX T 0 st e SFX T y iest [^aeiou]y SFX T 0 est [aeiou]y SFX T 0 est [^ey]
Первая строка класса аффикса является заголовком. Поля правил аффиксов перечисляются после заголовка:
имя параметра (PFX или SFX)
флаг (название класса аффикса)
удаление символов в начале (префиксе) или конце (суффиксе) слова
добавление приставки
условие, которое имеет формат, аналогичный формату регулярных выражений.
Файл .dict
выглядит как файл .dict
приложения
Ispell:
larder/M lardy/RT large/RSPMYT largehearted
Примечание
MySpell не поддерживает сложные слова. Hunspell имеет сложную поддержку сложных слов. В настоящее время Tantor BE реализует только основные операции со сложными словами Hunspell.
12.6.6. Snowball Словарь #
Шаблон словаря Snowball основан на проекте Мартина Портера (Martin Porter), изобретателя популярного алгоритма стемминга Портера для английского языка. Сейчас Snowball предоставляет алгоритмы стемминга для многих языков (см. сайт Snowball для получения дополнительной информации). Каждый алгоритм понимает, как привести общие варианты слов к базовой или корневой форме в пределах своего языка. Для работы со словарем Snowball требуется указать параметр language
, чтобы определить, какой стеммер использовать, и при необходимости можно указать имя файла stopword
, содержащего список слов для исключения. (Стандартные списки стоп-слов Tantor BE также предоставляются проектом Snowball).
Например, встроено определение, эквивалентное
CREATE TEXT SEARCH DICTIONARY english_stem ( TEMPLATE = snowball, Language = english, StopWords = english );
Формат файла стоп-слов такой же, как уже объяснялось.
Словарь Snowball распознает все, независимо от того, может ли он упростить слово, поэтому его следует поместить в конец списка словарей. Бесполезно иметь его перед любым другим словарем, потому что компонент никогда не пройдет через него к следующему словарю.