ПП в P
Полнотекстовый поиск в PostgreSQL 8.3
Олег Бартунов, Федор Сигаев
2008
ПП в Р - Prerequisites ●
●
Что такое БД и как пользоваться PostgreSQL 8.3+ (в предыдущих надо ставить contrib/tsearch2)
●
contrib/pg_trgm
●
Минимальные навыки работы с PgSQL
Олег Бартунов, Федор Сигаев
2008
ПП в P Поиск ● Поиск документов, удовлетворяющих запросу ● релевация ● Требования ● Полная интеграция с RDBMS (ACID) ● транзакции ● конкуррентность, восстановление после сбоя ● Моментальность (online) ● Морфология ● Гибкость ● Масштабируемость/производительность ●
Олег Бартунов, Федор Сигаев
2008
Документ для ПП
id --Title -----Abstract ----------Keywords ------------Body
Did ---Aid ----
id -Author ---------
Title || Abstract || Keywords || Body || Author
Олег Бартунов, Федор Сигаев
2008
Специальный типы для ПП
●
●
●
tsvector – представление документа для поиска tsquery – представление поискового запроса (&, |, !) Операция поиска tsquery @@ tsvector
Олег Бартунов, Федор Сигаев
2008
Создание значений tsvector
●
'мама:1 мыла:2 мою:3 раму:4'::tsvector
●
'награда:1 нашла:2 героя:3'::tsvector
●
to_tsvector([CFG,], TEXT): select to_tsvector('simple', 'Награда нашла героя'); to_tsvector --------------------------------'героя':3 'нашла':2 'награда':1
Олег Бартунов, Федор Сигаев
2008
Создание значений tsquery
●
'мама & раму'::tsquery
●
to_tsquery([CFG,] TEXT): select to_tsquery('simple', 'Мама & раму'); to_tsquery ----------------'мама' & 'раму'
●
plainto_tsquery([CFG,] TEXT): select plainto_tsquery('simple', 'Мама раму'); plainto_tsquery ----------------'мама' & 'раму'
Олег Бартунов, Федор Сигаев
2008
tsvector @@ tsquery
# select to_tsvector('simple', 'Мама мыла раму') @@ to_tsquery('simple', 'Мама & раму'); ?column? ---------t # select count(*) from posts where fts @@ plainto_tsquery('Неужели так просто?')
Олег Бартунов, Федор Сигаев
2008
Первый эксперимент
●
Таблица posts (мы благодарны пользователям, сгенерившим этот пример)
●
Колонка tsvector
●
Заполнение колонки
●
Все!
●
Все?!
Олег Бартунов, Федор Сигаев
2008
Разгон поиска - индексы
GIN ●
Быстрый поиск
●
Медленная вставка
GIST ●
Медленный поиск
●
Быстрая вставка
Олег Бартунов, Федор Сигаев
2008
А морфология?
Словари – „инфинитизация“ слов # \dFp+
Олег Бартунов, Федор Сигаев
2008
to_tsvector() DOCUMENT PARSER (token, token_type) dicts(token_type) YES i=0
YES
ask DICT[i]
YES
YES IS STOP ?
NO
NO NO
Олег Бартунов, Федор Сигаев
i=i+1
i
NO
tsvector 2008
Конфигурации
●
\dF
●
\dF+ russian
●
# SELECT to_tsvector('russian', 'Мама мыла раму'); to_tsvector ------------------------'мам':1 'мыл':2 'рам':3
●
# SELECT plainto_tsquery('russian', 'Мамы рамы'); plainto_tsquery ----------------'мам' & 'рам'
Олег Бартунов, Федор Сигаев
2008
Snowball \dF+ russian # SELECT to_tsvector('russian', 'валил валившийся вал'); to_tsvector ------------'вал':1,2,3 #
SELECT to_tsvector('russian', 'вокзал в вокзале'); to_tsvector ---------------------'вокза':1 'вокзал':3
#
SELECT to_tsvector('russian', 'батарея батарею'); to_tsvector ---------------------'батар':2 'батаре':1
Олег Бартунов, Федор Сигаев
2008
Ispell, Myspell, Hunspell
http://wiki.services.openoffice.org/wiki/Dictionaries % unzip ru_RU.zip % iconv -f koi8-ru -t utf-8 < ru_RU.aff > /usr/local/pgsql/share/tsearch_data/ru_ru.affix % iconv -f koi8-ru -t utf-8 < ru_RU.dic > /usr/local/pgsql/share/tsearch_data/ru_ru.dict
Олег Бартунов, Федор Сигаев
2008
Ispell - настройка
# CREATE TEXT SEARCH DICTIONARY ru_ispell ( TEMPLATE = ispell, DictFile = ru_ru, AffFile = ru_ru, StopWords = russian ); # CREATE TEXT SEARCH CONFIGURATION ru (COPY = russian); # ALTER TEXT SEARCH CONFIGURATION ru ALTER MAPPING FOR hword, hword_part, word WITH ru_ispell, russian_stem;
Олег Бартунов, Федор Сигаев
2008
Ы? # SELECT to_tsvector('ru', 'валил валившийся вал'); to_tsvector ----------------------------------'вал':3 'валить':1 'валившийся':2 # SELECT to_tsvector('ru', 'вокзал в вокзале'); to_tsvector -------------'вокзал':1,3 # SELECT to_tsvector('ru', 'батарея батарею'); to_tsvector --------------'батарея':1,2 # SELECT to_tsvector('ru', 'незастолбленное слово'); to_tsvector ---------------------------слово':2 'незастолблен':1 Олег Бартунов, Федор Сигаев
2008
Отладка
● ● ● ● ● ● ●
\dF \dFd \dFt \dFp ts_debug() ts_lexize() ts_parse()
Олег Бартунов, Федор Сигаев
2008
Релевация
●
ts_rank([real[],] tsvector, tsquery[, int4] )
●
ts_rank_cd([real[],] tsvector, tsquery [, int4])
4 класса лексем – A,B,C,D (default): SELECT setweight(to_tsvector('ru', 'Солнце'), 'A') || to_tsvector('ru', 'Это просто звезда'); SELECT id, ts_rank_cd(fts, q) AS r FROM posts, plainto_tsquery('ru', 'Москва') AS q WHERE fts @@ q ORDER BY r DESC LIMIT 10;
Олег Бартунов, Федор Сигаев
2008
Headline/выжимка ts_headline([CFG,] TEXT, TSQUERY [, OPTS]) # SELECT nextval, ts_headline('ru', msg_text, q), ts_rank_cd(fts, q) AS r FROM posts, plainto_tsquery('ru', 'Москва Питер') AS q WHERE fts @@ q ORDER BY r DESC LIMIT 10;
Опции: ●
StartSel, StopSel
●
MaxWords, MinWords
●
ShortWord
●
HighlightAll
Олег Бартунов, Федор Сигаев
2008
Продвинутые словари
●
Synonym – замена слова на слово
●
Thesaurus – замена фразы на фразу
●
Словарь чисел 3.14159265358979323846 => 3.14
●
Regex словарь
●
Профессинальные словари
●
Словарь химических формул
Олег Бартунов, Федор Сигаев
2008
Типсы и Триксы - 1 ●
●
default_text_search_config Триггеры tsvector_update_trigger и tsvector_update_trigger_column
●
tsvector || tsvector
●
setweight(), strip()
●
●
tsquery && tsquery tsquery || tsquery !! tsquery numnode(tsquery), length(tsvector), querytree(tsquery)
Олег Бартунов, Федор Сигаев
2008
Типсы и Триксы - 2
●
●
●
SELECT id, ts_headline('ru', msg_text, q), r FROM ( SELECT *, ts_rank_cd(fts, q) AS r FROM posts, plainto_tsquery('ru', 'Москва Питер') AS q WHERE fts @@ q ORDER BY r DESC LIMIT 10 ) AS res; SELECT ... @@ to_tsquery('Солнце:AB'); UPDATE tbl SET fts= setweight( coalesce( to_tsvector(title),''),'B') || setweight( coalesce( to_tsvector(keywords),''),'A') || setweight( coalesce( to_tsvector(body),''),'D'); (tsvector || NULL) => NULL Олег Бартунов, Федор Сигаев
2008
Типсы и Триксы - 3
●
●
SELECT * FROM ts_stat('SELECT fts FROM posts') ORDER BY ndoc DESC; To be or not to be. Блин! Две конфигурации – со стоп-словами и без. Первая – для поиcка по умолчанию, вторая – для индексации и поиска по требованию пользователя.
Олег Бартунов, Федор Сигаев
2008
Типсы и триксы - 4
●
●
Курск столкнулся с Останкинской башней. Курск – город или подводная лодка? Query rewriting: - New York => Gottham, NYC, Big Apple - Курск => подводная лодка Курск А нужны ли позиции и релевирование? strip()
Олег Бартунов, Федор Сигаев
2008
Типсы и Триксы - 5
VLDB (Very Large Database) ●
Partitioning, sharding (и по серверам тоже, релевация не зависит от коллекции!)
●
GIN на архивной части
●
GiST на свежей части
●
gin_fuzzy_search_limit
Олег Бартунов, Федор Сигаев
2008
Типсы и Триксы - 6
Синтаксис Морфология
Веса
''::tsquery
Y
N
Y
to_tsquery()
Y
Y
Y
plain_to_tsquery()
N
Y
N
Создавайте свои обертки с помощью to_tsquery и ||, && и !! Олег Бартунов, Федор Сигаев
2008
pg_trgm - инсталляция
% cd contrib/pg_trgm % gmake && su -c 'gmake install' && gmake installcheck % psql DB < /usr/local/pgsql/share/contrib/pg_trgm.sql
Олег Бартунов, Федор Сигаев
2008
pg_trgm # SELECT show_trgm('Черная дыра'); show_trgm -------------------------------------------------------------{"ая ",дыр,ерн,ная,"ра ",рна,ыра,чер," ды"," че"," д"," ч"} # SELECT similarity('Черная дыра' , 'Белая дыра'); similarity -----------0.352941 # SELECT show_limit(); show_limit -----------0.3 # SELECT 'Черная дыра' % 'Белая дыра'; ?column? ---------t Олег Бартунов, Федор Сигаев
2008
pg_trgm
# SELECT *, similarity(name, 'дыра чрная') AS s FROM keywords WHERE name % 'дыра чрная' ORDER BY s DESC; id | name | s ---------+---------------+---------6386 | черная дыра | 0.642857 6388 | Черная дыра | 0.642857 2927 | белая дыра | 0.375 1428 | озоновая дыра | 0.315789 Индексы – GIN или GiST Олег Бартунов, Федор Сигаев
2008
Ссылки
●
http://www.postgresql.org/docs/8.3/static/
●
http://www.sai.msu.su/~megera/postgres/
●
http://www.sigaev.ru/
Олег Бартунов, Федор Сигаев
2008
Хотите ответов?
Задавайте вопросов
Олег Бартунов, Федор Сигаев
2008