В этой статье я опишу весь путь от установки до использования системы полнотекстового поиска Sphinx.

Для наглядности примера, пускай у нас есть таблица с улицами и нам нужно делать поиск по ней. Понимаю что улиц не так много, вместо них могут быть телефоны или что-то подобное, с большим количеством записей.

 

 

 

01. Установка и конфигурирование sphinx

Ради sphinx’а пересел обратно в ubuntu и, что удивило, помоему убунту стала намного стабильнее. Наверное даже не сама система, сколько приложения, которыми я пользуюсь, пока что и не собираюсь возвращаться на винду(кс – есть, а это главное :)).

Установка занимает ровно 1 команду:

sudo apt-get install sphinxsearch

Грубо говоря сфинкс парсит данные напрямую из mySQL, в конфиге сфинкса указываем SQL запрос, который и будет потом индексирован. Вообще сам конфиг делится на 3 части: источники данных, параметры индексации и параметры самого сервера. Суть следующая индекс включает в себя один или несколько источников данных и путь до места, где этот индекс хранится. Если источников несколько, то они должны быть однородны (одинаковое количество столбцов). После обработки поискового запроса, sphinx возвращает id найденных записей. Соответственно в источнике нужно указать какое поле и будет браться как id. Причем их может быть несколько.

Перейдем непосредственно к примеру: у нас есть таблица street, содержащая id и street_name. Теперь нам нужно отконфигурировать сам сфинкс, для этого будем править файл /etc/sphinxsearch/sphinx.conf.

Конфиг для источника данных:

source street_name {
    type = mysql
    sql_host = 127.0.0.1
    sql_user = root
    sql_pass =
    sql_db = test
    sql_port = 3306
    sql_query_pre = SET NAMES utf8
    sql_query = SELECT id, street_name FROM street
    sql_attr_uint = id
    sql_query_info = SELECT street_name FROM street WHERE id=$id  
}

Здесь sql_query – это тот самый запрос, который будет проиндексирован, а sql_query_info – это вспомогательный запрос, который будет показываться, ну например при тестировании работы сфинкса из консоли.

Конфиг для индекса:

index street {
   source = street_name
   path = /var/lib/sphinxsearch/data/street
   morphology = stem_ru
   min_word_len = 1
   charset_type = utf-8
 }

Заметьте, что в качестве источника мы используем street_name – имя источника. Далее идет путь до места, где будет храниться индекс и прочие настройки.

И последние, в этом же файле должен быть конфиг для самого процесса сфинкс:

searchd {
   listen = 127.0.0.1:9306:mysql41
   log = /var/log/sphinxsearch/searchd.log
   query_log = /var/log/sphinxsearch/query.log
   pid_file = /var/run/sphinxsearch/searchd.pid
   read_timeout = 5
   max_children = 30
   max_matches = 1000
   seamless_rotate = 1
   preopen_indexes = 0
   unlink_old = 1
 }

Описывать подробно его не буду – все параметры можно посмотреть на сайте сфинкса.

02. Индексирование

Для первоначального индекса в консоли запустим команду:

sudo indexer street

Ниже – результаты:

 Copyright (c) 2001-2012, Andrew Aksyonoff
 Copyright (c) 2008-2012, Sphinx Technologies Inc (   http://sphinxsearch.com)
 using config file '/etc/sphinxsearch/sphinx.conf'...
 indexing index 'street'...
 WARNING: attribute 'id' not found - IGNORING
 WARNING: Attribute count is 0: switching to none docinfo
 WARNING: collect_hits: mem_limit=0 kb too low, increasing to 12288 kb
 collected 3402 docs, 0.1 MB
 sorted 0.0 Mhits, 100.0% done
 total 3402 docs, 129590 bytes
 total 0.054 sec, 2380462 bytes/sec, 62491.96 docs/sec
 total 2 reads, 0.000 sec, 24.5 kb/call avg, 0.0 msec/call avg
 total 6 writes, 0.000 sec, 17.5 kb/call avg, 0.0 msec/call avg

Видно, что проиндексировал 3402 записей и теперь также протестируем в консоли индекс:

search -i street Ленина

Выбираем в качестве индекса street и по ней делаем поиск по слову Ленина. Я получил id двух записей – 2891 и 2892. Это id совпавших записей в нашей таблице.

Второе что нужно знать – в случае если у нас добавятся улицы и нужно будет переиндексировать таблицу, используем команду:

sudo indexer --rotate --all

03. Shpinx и Yii framework

Теперь, когда у нас есть индекс, нужно подключить сфинкс к yii. Можно использовать расширение, но мне оно сразу не понравилось, вылезло кучу ошибок, какие-то эксепшены, поэтому я воспользовался рецептом Загирова Рустама – http://www.zagirov.name/yii-cookbook-2 и подключил сфинкс как компонент:

1
2
3
4
'sphinx' => array(
 'class' => 'system.db.CDbConnection',
 'connectionString' => 'mysql:host=127.0.0.1;port=9306',
),

Далее просто создаем запрос на выборку данных, аналогичино работы с MySQL:

1
$sSql = 'SELECT id FROM street WHERE MATCH(' . Yii::app()->sphinx->quoteValue($term) . ')';

И выполняем запрос:

1
$ids = Yii::app()->sphinx->createCommand($sSql)->queryAll();

Теперь $ids содержит массив с id улиц. Далее конкретные названия, если они нужны, можно получить, используя обычный AR.