SphinxSearch и MongoDB на примере HaipIT News

Приветствую, Земляне!

В данной статье я расскажу, как настроить поиск Sphinx таким образом, чтобы он мог выполнять индексацию базы данных Mongo (про работу с индексом через PHP код в другой раз).

Наверно многие из вас в курсе, что последние пару неделю я работаю над очередным своим проектом под названием HaipIT News, суть данного проекта — агрегация новостей из некоторых любимых мною источников. Проект пока ещё находится в стадии разработки. но уже много чего сделано, например API которое работает напрямую с базой данных MongoDB и ряд скриптов для импорта новостей из источников и частично завершённый Web-интерфейс.

Изначально для поиска я планировал реализовать связку MongoDB и ElasticSearch, это у меня получилось при помощи специального плагина. Наигравшись с ElasticSearch пришёл к выводу, что это не самая подходящая для меня система. Да, у ElasticSearch очень круто настраиваются словари, очень легко реализовать интеграцию в код, из коробки поддерживаются кластеры Mongo, но со временем Elastic стала очень странно себя вести, ps aux и service status показывали что всё нормально, но любая попытка сделать запрос возвращала null. После нескольких попыток заставить Elastic работать (restart в crontab помогал некоторое время), я разочаровался в этой идее и принялся искать более надёжное решение. И им, как не сложно догадаться, оказался Sphinx, у меня уже был большой опыт работы с данных сервером раньше, но я никогда не настраивал индексацию MongoDB.

Как показала практика, сделать это очень просто:

Sphinx (установить и настроить)

Для счастливых обладателей Debian-like дистрибутивов всё должно быть очень просто:

sudo apt-get install sphinxsearch

Дальше создадим конфиг, который будет запускать генератор XML:

sudo mcedit /etc/sphinxsearch/sphinx.conf

Запишем в него следующее

source src_mongo {
type = xmlpipe2
xmlpipe_command = /usr/bin/php /home/king/sphinx-index.php
}

index mongo {
morphology      = stem_enru
charset_type    = utf-8
source          = src_mongo
path            = /var/lib/sphinxsearch/data/mongo
}

indexer
{
mem_limit               = 128M
}

searchd
{
listen                  = 9312
listen                  = 9306:mysql41
log                     = /var/log/sphinxsearch/searchd.log
query_log               = /var/log/sphinxsearch/query.log
read_timeout            = 5
max_children            = 30
pid_file                = /var/run/sphinxsearch/searchd.pid
seamless_rotate         = 1
preopen_indexes         = 1
unlink_old              = 1
workers                 = threads # for RT to work
binlog_path             = /var/lib/sphinxsearch/data
}

Жирным шрифтом я выделил пару моментов:

  • xmlpipe2 — тип данного источника, для всех современных версий Sphinx стоит выбирать именно его, так как первая версия просто не работает
  • /home/king/sphinx-index.php — название и путь к скрипту генератору, это может быть любая программа или скрипт, главное чтобы данные которые он возвращает в процессе работы были в формате XML, php показан только как пример
  • mongo — название нашего индекса, оно понадобится нам в дальнейшем

Скрипт, для генерации XML

Создадим файл /home/king/sphinx-index.php:

mcedit /home/king/sphinx-index.php

Со следующим содержимым:

<?php
$filter = [];
$options = [];
$query = new MongoDB\Driver\Query($filter, $options);
$rows = $mongo->executeQuery(‘myDB.myCollection’, $query);

echo ‘<?xml version = «1.0» encoding = «utf-8″?>’;
?>
<sphinx:docset>

<sphinx:schema>
<sphinx:attr name=»_id» type=»string»/>
<sphinx:field name=»content»/>
</sphinx:schema>

<?php
$i = 1;
foreach ($rows as $document) {
?>
<sphinx:document id=»<?php echo $i ?>»>
<_id><?php echo $document->_id ?></_id>
<content><![CDATA[[<?php echo $document->content ?>]]></content>
</sphinx:document>
<?php
$i++;
}
?>

</sphinx:docset>

Выполнение данного скрипта должно отображать нам что-то вроде:

<?xml version = «1.0» encoding = «utf-8″?>
<sphinx:docset>

<sphinx:schema>
<sphinx:attr name=»_id» type=»string»/>
<sphinx:field name=»content»/>
</sphinx:schema>

<sphinx:document id=»1″>
<_id>5907466c6b02a304e855f47f</_id>
<content><![CDATA[[some text with html tags]]></content>
</sphinx:document>

…………lot of results………….

</sphinx:docset>

Если Вы видите что-то подобное, значит всё хорошо и данные из монги выгружаются как надо, на самом деле это может быть какая угодно база данных (а может вы хотите индексировать файловую систему), важно только чтобы данные были в формате XML.

Выполним индексацию

Тут всё просто, для того чтобы выполнить индексацию нужно выполнить следующую команду:

sudo indexer mongo

Где mongo это название индекса, который мы прописали в конфиге /etc/sphinxsearch/sphinx.conf. В дальнейшем мы будем только обновлять индекс, следующей командой:

sudo indexer mongo —rotate

Я добавил её в крон, чтобы индексация происходила автоматически, без моего участия.

Завершение

Как видно из статьи, реализовать индексацию данных, находящихся в Mongo очень просто, работать с индексом так же просто как настраивать его. А высокая скорость работы будет радовать Вас ещё очень долго, если время отклика важно для Вас. Например моя база (на момент выхода данной заметки), содержит в себе около 10000 документов, размер индекса составляет около 10Мбайт, а время генерации индекса почти одна секунда, неплохой результат как по мне.

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

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