Система сбора отзывов Cackle Reviews с полнотекстовым поиском

от автора

Всем привет! Не так давно мы реализовали полнотекстовый поиск для системы сбора отзывов Cackle Reviews. Получилось здорово, теперь любой модератор за несколько миллисекунд может найти интересующие его отзывы по слову или предложению с поддержкой стемминга (нечёткого поиска по части слова или его словоформам). Всё это работает на Sphinx — системе полнотекстового поиска.

В интернете есть много статей о Sphinx, но, к сожалению, часть из них устарела, некоторые другие не претендуют на полный и точный how to. Так что в данном посте мы постарались изложить все шаги — установки, настройки, индексации и поддержке дельта индекса.

система отзывов Cackle Reviews с полнотекстовым поиском

1. Установка Sphinx

Как уже было сказано Sphinx — это система полнотекстового поиска. Выбор на Sphinx пал не случайно, дело в том, что данная система является самой быстрой исходя из некоторых тестов сравнения скорости и возможностей движков подобных систем.

С документацией по установке все не так хорошо. Итак, для взаимодействия со Sphinx нам нужен — клиент MySQL (для работа с API Sphinx) и сам Sphinx. Ниже команды установки всех необходимых библиотек для Linux (в примере используется Linux Debian 8 64bit).

# Для установки клиента MySQL через apt-get прописываем необходимый репозиторий в /etc/apt/sources.list deb http://repo.mysql.com/apt/debian/ wheezy mysql-5.6 deb-src http://repo.mysql.com/apt/debian/ wheezy mysql-5.6  # Установка клиента MySQL apt-get install mysql-client unixodbc libpq5 libmysqlclient18  # Скачиваем последнюю версию Sphinx (на момент написания статьи 2.2.9) wget http://sphinxsearch.com/files/sphinxsearch_2.2.9-release-1~wheezy_amd64.deb  # Устанавливаем dpkg -i sphinxsearch_2.2.9-release-1~wheezy_amd64.deb 

2. Настройка Sphinx

Если установка прошла нормально, то в Linux должен появится демон sphinxsearch, который пока можно остановить (/etc/init.d/sphinxsearch stop). Далее нужно создать структуру каталогов для хранения индексов, в нашем случае их будет два — основной и дельта индекс. Основной хранит все данные, дельта только за сегодняшний день для ускорения индексации.

mkdir /opt/sphinx mkdir /opt/sphinx/data  # Основной индекс mkdir /opt/sphinx/data/review  # Дельта индекс mkdir /opt/sphinx/data/review_delta  # Логи mkdir /opt/sphinx/log/ 

Редактируем конфигурацию Sphinx (по умолчанию /etc/sphinxsearch/sphinx.conf). Необходимо уточнить, что все отзывы хранятся в таблице review и индексируются поля:

  • id — идентификатор отзыва;
  • site_id — идентификатор сайта, на котором расположен отзыв;
  • status — статус отзыва (Одобрен, На модерации, Спам, Удален);
  • pros — достоинства;
  • cons — недостатки;
  • comment — комментарий.

# Базовая конфигурация источника, который будем индексировать (БД PostgreSQL) source base {   type = pgsql   sql_host =  162.198.0.3   sql_user = postgres_login   sql_pass = postgres_password   sql_db = cackle   sql_port = 5179 }  # Базовая конфигурация индекса index base {   # Кодировка   charset_type = utf-8    # Поддержка стемминга для Английских и Русских слов   morphology = stem_enru    # Минимальное слово для индексации 2 символа   min_word_len = 2 }  # Источник review наследованный от базовой конфигурации source review : base {   # Перед индексацией очистить таблицу search_fulltext   # и вставить в неё максимальный id из таблицы review (данный id в search_fulltext нужен для дельта индекса)   sql_query_pre	= DELETE FROM search_fulltext WHERE type = 'review'   sql_query_pre	= INSERT INTO search_fulltext SELECT 'review', MAX(id) FROM review    # Индексируем поля id, site_id, status, pros, cons, comment из таблицы review   sql_query = SELECT id, site_id, status, pros, cons, comment FROM review    # Добавляем фильтр по идентификатору сайта   sql_attr_uint = site_id    # Добавляем фильтр по статусу отзыва (Одобрен, На модерации, Спам, Удален)   sql_attr_uint = status }  # Индекс review наследованный от базовой конфигурации индекса работает с источником review # и хранится в /opt/sphinx/data/review index review : base {   source = review   path = /opt/sphinx/data/review }  # Дельта источник наследованный от review source review_delta : review {    # Так как не нужно, чтобы выполнялись sql_query_pre из родительской конфигурации источника review    # делаем обходной приём - вызов пустого SQL (SELECT 1)   sql_query_pre = SELECT 1    # Для индексации выбираем всё те же поля, но с id, которые больше чем id из таблицы search_fulltext   sql_query = SELECT id, site_id, status, pros, cons, comment FROM review WHERE id > (SELECT id FROM search_fulltext WHERE type = 'review') }  # Дельта индекс index review_delta : review {   source = review_delta   path = /opt/sphinx/data/review_delta }  # Конфигурация демона searchd # обязательно пропишите версию mysql (mysql_version_string = 5.5.21) без этого к клиенту было не подключится searchd {   listen = localhost:9306:mysql41   mysql_version_string = 5.5.21    log = /opt/sphinx/log/searchd.log   query_log = /opt/sphinx/log/query.log   pid_file = /opt/sphinx/log/searchd.pid } 

3. Запуск

Все готово, можно запустить демона searchd (/etc/init.d/sphinxsearch start) и начать индексацию review (основной индекс):
indexer --config /etc/sphinxsearch/sphinx.conf review

полнотекстовый поиск отзывов Cackle Reviews


Итак, все 730422 отзыва были проиндексированы за 84 секунды. Теперь можно подключится к Sphinx через MySQL (mysql://localhost:9306) и попробовать поиск через SQL команды:

# Найти id отзывов на сайте с идентификатором 1 и текстом 'тест', сортировка на id, выборка от 0 до 15 SELECT id FROM review WHERE site_id = 1 AND MATCH('тест') ORDER BY id DESC LIMIT 0,15  # Найти id отзывов на сайтах с идентификаторами 1, 2, 738, 35302 и статусами 1 (одобрен), 3 (спам) SELECT id FROM review WHERE site in (1, 2, 738, 35302) AND status in (1, 3) AND MATCH('хороший продукт')   ORDER BY id DESC LIMIT 0, 15 

За несколько миллисекунд мы получим id отзывов, по которым далее можно сделать выборку из основной БД из таблицы review и вернуть результат клиенту.

4. Настройка дельта индекса

Как уже было сказано, дельта индекс нужен для быстрой индексации небольшого размера данных. В нашем случае это все новые отзывы накопленные за текущий день. Для данной настройки создаем в кроне 2 джобы:

crontab -e  # Каждые 5 минут запускаем индексацию review_delta (все отзывы id которых больше чем id из таблицы search_fulltext) */5 * * * * indexer --rotate --quiet --config /etc/sphinxsearch/sphinx.conf review_delta  # Раз в сутки (в час ночи) выполняем скрипт review_update.sh 0 1 * * * /opt/sphinx/review_update.sh 

Скрипт review_update.sh запускает индексацию review_delta, обновляет максимальный id в таблице search_fulltext и мержит результат review и review_delta индексов.

PGPASSWORD=postgres_password; export PGPASSWORD; indexer --rotate --quiet --config /etc/sphinxsearch/sphinx.conf review_delta; psql --host 162.198.0.3 --port 5179 --username "postgres_login" -c "UPDATE search_fulltext SET id = (SELECT MAX(id) FROM review) WHERE type = 'review'" "cackle"; indexer --merge review review_delta --rotate --quiet --config /etc/sphinxsearch/sphinx.conf; 

После этого в SQL запросы поиска можно добавить таблицу review_delta и тогда выборка будет сразу из 2 индексов — основного и дельта.

# Найти id отзывов на сайте с идентификатором 1 и текстом 'тест', сортировка на id, выборка от 0 до 15 SELECT id FROM review, review_delta WHERE site_id = 1 AND MATCH('тест') ORDER BY id DESC LIMIT 0,15  # Найти id отзывов на сайтах с идентификаторами 1, 2, 738, 35302 и статусами 1 (одобрен), 3 (спам) SELECT id FROM review, review_delta WHERE site in (1, 2, 738, 35302) AND status in (1, 3) AND MATCH('хороший продукт')   ORDER BY id DESC LIMIT 0, 15 

Данная реализация заняла всего день работы, в итоге с помощью неё мы создали стабильный полнотекстовый поиск, который без единого сбоя работает уже несколько месяцев. Кстати, добавив подобную конфигурацию и джобу (review заменяется на comment) для системы комментирования Cackle Comments, был реализован поиск по комментариям.

Вопросы в приветствуются. Спасибо за внимание. Всем успехов!

ссылка на оригинал статьи http://habrahabr.ru/post/261829/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *