image

Обратился к нам клиент с просьбой обновить 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('? & ?');

Вопросы, предложения и пожелания пишите в комментах.
Спасибо за внимание!
Поделиться с друзьями
-->

Комментарии (2)


  1. apro
    26.05.2016 12:45

    Точнее, оптимизировать процесс полнотекстового поиска на китайском, ибо тормозило все это дело нещадно.


    А можно поподробнее почему нужен zhparser и как он решает проблему тормозов?


    1. akhaustov
      30.05.2016 10:58

      На самом деле, тормозило из-за того, что до начала работ поиск работал через like. Так что zhparser тут скорее как нужный в реализации full text search есктеншн.