Данная статья описывает конфигурирование FTS в PostgreSQL .
О самом FTS: Full-Text Search in PostgreSQL by Oleg Bartunov, Teodor Sigaev
О самом FTS: Full-Text Search in PostgreSQL by Oleg Bartunov, Teodor Sigaev
Исходная ситуация:
- gentoo linux
- локаль koi8r
- база должна быть в utf8
- полнотекстовый поиск с учётом лексического анализа
# emerge =dev-db/postgresql-8.2.4-r1
При инициализации кластера бд (initdb) лучше изменить локаль на ru_RU.utf8, чтобы весь кластер в целом был utf8, либо при создании бд указываем encoding UTF8
Создаём пользователя, бд.
Вливаем tsearch2
$ psql -U dbuser dbname < /usr/share/postgresql/contrib/tsearch2.sql
Гут.
По-умолчанию, есть только en_stem и ru_stem - которые могут делать разбор слов без лексического анализа.
в path_to_db/postgresql.conf :
# actually, defaults to database encoding
# Замечание : только если текущая системная локаль koi8r !
client_encoding = koi8r
# These settings are initialized by initdb -- they might be changed
# locale for system error message strings
lc_messages = 'C'
# locale for monetary formatting
lc_monetary = 'ru_RU.utf8'
# locale for number formatting
lc_numeric = 'ru_RU.utf8'
# locale for time formatting
lc_time = 'ru_RU.utf8'
Установим, используемую локаль text search'а на utf8_russian :
DELETE FROM pg_ts_cfg WHERE ts_name='default_russian';
UPDATE pg_ts_cfg set locale='ru_RU.utf8' WHERE ts_name='utf8_russian';
UPDATE pg_ts_cfg set locale='C' WHERE ts_name='default';
UPDATE pg_ts_cfg set locale='' WHERE ts_name='simple';
Замечание: TSearch2 выбирает из pg_ts_cfg первую локаль из списка, после такой последовательности UPDATE'ов желаемая локаль будет первой в списке.
Вместо *_stem будем использовать *_ispell: Привязываем русские словари:
# emerge ispell-ru # iconv /usr/lib/ispell/russian.dict -t utf8 -o /usr/lib/ispell /russian_utf8.dict
# iconv /usr/lib/ispell/russian.aff -t utf8 -o /usr/lib/ispell /russian_utf8.aff
И английские:
# iconv /usr/lib/ispell/english.aff -t utf8 -o /usr/lib/ispell /english_utf8.aff
INSERT into pg_ts_dict SELECT 'ru_ispell', dict_init,
'DictFile="/usr/lib/ispell/russian_utf8.dict",
AffFile="/usr/lib/ispell/russian_utf8.aff",
StopFile="/usr/share/postgresql/contrib/russian.stop.utf8"',
dict_lexize FROM pg_ts_dict WHERE dict_name='ispell_template';
INSERT into pg_ts_dict SELECT 'en_ispell', dict_init,
'DictFile="/usr/lib/ispell/english.dict",
AffFile="/usr/lib/ispell/english_utf8.aff",
StopFile="/usr/share/postgresql/contrib/english.stop"',
dict_lexize FROM pg_ts_dict WHERE dict_name='ispell_template';
DELETE FROM pg_ts_cfgmap
WHERE ts_name IN ('default_russian', 'utf8_russian')
AND tok_alias IN ('hword', 'lhword', 'lpart_hword', 'lword', 'word',
'nlhword', 'nlpart_hword', 'nlword');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'hword', '{ru_ispell,ru_stem_utf8}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'word', '{ru_ispell,ru_stem_utf8}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'lhword', '{en_ispell,en_stem}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'lpart_hword', '{en_ispell,en_stem}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'lword', '{en_ispell,en_stem}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'nlhword', '{ru_ispell,ru_stem_utf8}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'nlpart_hword', '{ru_ispell,ru_stem_utf8}');
INSERT INTO pg_ts_cfgmap (ts_name, tok_alias, dict_name)
VALUES ('utf8_russian', 'nlword', '{ru_ispell,ru_stem_utf8}');
Всё :)
select ts_debug( 'car, cars, мама, мамы, маму, мамой ');
ts_debug
--------------------------------------------------------------------------------
(utf8_russian,lword,"Latin word",car,"{en_ispell,en_stem}",'car')
(utf8_russian,lword,"Latin word",cars,"{en_ispell,en_stem}",'car')
(utf8_russian,nlword,"Non-latin word",мама,"{ru_ispell,ru_stem_utf8}",'мама')
(utf8_russian,nlword,"Non-latin word",мамы,"{ru_ispell,ru_stem_utf8}",'мама')
(utf8_russian,nlword,"Non-latin word",маму,"{ru_ispell,ru_stem_utf8}",'мама')
(utf8_russian,nlword,"Non-latin word",мамой,"{ru_ispell,ru_stem_utf8}",'мама')
(6 rows)
SELECT * from to_tsvector('default_russian', 'дон, донья, пень, пни, пней, пнями, пну');
to_tsvector
----------------------------------------------
'дон':1 'пень':3,4,5,6 'донья':2 'пнуть':4,7
(1 запись)
3 комментария:
Хмммм ... замечательно
А не подскажете, как то же самое сделать в постгресе 7.4 ?
Попробовал, почти работает, но ispell похоже не помогает, мамы & маму так и остается мамы & маму, не переводится в каноническую форму.
про 7.* увы подсказать ничего не смогу, ибо не сталкивался - нужно гуглить.
Если "мамы & маму" так и остаётся "мамы & маму", значит, что ispell не работает и приоритет находится, скорей всего у strem
Здравствуйте, может вы знаете...
С чего начать не знаю.
У меня нет словаря на русском..
т.е.
Выполняю такой запрос
CREATE TEXT SEARCH DICTIONARY mydict_russian_ispell (
TEMPLATE = ispell,
DictFile = russian,
AffFile = russian,
StopWords = russian
);
получаю ошибку
ERROR: could not open dictionary file "C:/Program Files (x86)/PostgreSQL/8.4/share/tsearch_data/russian.dict": No such file or directory
Подскажите в чем дело.
Отправить комментарий