Обратился к нам клиент с просьбой обновить PostgreSQL до самой свежей версии, а заодно и научить его китайскому.
Точнее, оптимизировать процесс полнотекстового поиска на китайском, ибо тормозило все это дело нещадно.
Ниже описано как это нами было сделано.
Сразу перейдем к делу.
Первым делом нужно собрать и установить Simple Chinese Word Segmentation (SCWS) и само расширение zhparser
SCWS
wget -q -O - http://www.xunsearch.com/scws/down/scws-1.2.2.tar.bz2 | tar xf -
cd scws-1.2.2 ; ./configure ; make install
Теперь zhparser
github.com/amutu/zhparser — тут есть заодно и полноценная инструкция, по ней и делаем.
git clone https://github.com/amutu/zhparser.git
SCWS_HOME=/usr/local make && make install
Если собралось успешно, включаем расширение в нужной базе
psql -U postgres -d test_dbname -c 'CREATE EXTENSION zhparser'
Далее, идем в нужную базу и создаем конфигурацию
test_dbname=# CREATE TEXT SEARCH CONFIGURATION testzhcfg (PARSER = zhparser);
test_dbname=# ALTER TEXT SEARCH CONFIGURATION testzhcfg ADD MAPPING FOR n,v,a,i,e,l WITH simple;
Допустим, у нас уже есть таблица с данными.
CREATE TABLE messages (
title text,
body text
);
И нам нужно осуществлять поиск по колонкам title и body. Пусть там будет такая запись
INSERT INTO messages VALUES('批发新', '款新婴幼');
Для этого нам нужно добавить колонку tsv c типом tsvector для лексем.
test_dbname=# ALTER TABLE messages ADD COLUMN tsv tsvector;
Вешаем на неё индекс gin (https://ru.wikipedia.org/wiki/GIN)
test_dbname=# CREATE INDEX tsv_idx ON messages USING gin(tsv);
Теперь, создаем триггер, для автоматического обновления лексем в колонке tsv, используя нашу конфигурацию public.testzhcfg, которую создавали ранее.
test_dbname=# CREATE TRIGGER tsvectorupdate BEFORE INSERT OR UPDATE ON messages FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger( tsv, 'public.testzhcfg', title, body );
И последний шаг.
Нужно обновить колонку tsv нашим новым триггером. (а он как мы видим активируется при insert и update), для этого мы через UPDATE переписываем текущие значения полей title и body, теми же значения.
test_dbname=# UPDATE messages SET title=title, body=body;
Можно пробовать
SELECT title, body FROM messages WHERE tsv @@ to_tsquery('批 & 款');
Вопросы, предложения и пожелания пишите в комментах.
Спасибо за внимание!