You are on page 1of 32

ПП в P

Полнотекстовый поиск
в
PostgreSQL 8.3

Олег Бартунов, Федор Сигаев 2008
ПП в Р - Prerequisites

● Что такое БД и как пользоваться
● PostgreSQL 8.3+ (в предыдущих надо
ставить contrib/tsearch2)
● contrib/pg_trgm
● Минимальные навыки работы с PgSQL

Олег Бартунов, Федор Сигаев 2008
ПП в P

● Поиск
● Поиск документов, удовлетворяющих запросу

● релевация

● Требования

● Полная интеграция с RDBMS (ACID)

● транзакции

● конкуррентность, восстановление после сбоя

● Моментальность (online)

● Морфология

● Гибкость

● Масштабируемость/производительность

Олег Бартунов, Федор Сигаев 2008
Документ для ПП

id
--- id
Title Did --
------ ---- Author
Abstract Aid ---------
----------- ----
Keywords
-------------
Body

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)
NO
YES
i=0 YES
ask DICT[i]
i=i+1 i<N
NO NO
YES
IS STOP ? tsvector
YES NO
Олег Бартунов, Федор Сигаев 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