Поиск при помощи Sphinx и PHP

Настройку Sphinx можно разбить на 3 этапа:

1. Установка Sphinx и конфигурирование.
2. Создание индекса базы и тестовый поиск из консоли.
3. Поиск из PHP.

Установка Sphinx не сложная.

Для windows: идём на официальный сайт и скачиваем дистрибутив.

Для Ubuntu достаточно воспользоваться командой

apt-get install sphinxsearch

После того как Sphinx установлен, можно приступать к конфигурированию. Так как Sphinx может обрабатывать запросы от нескольких проектов, логично было бы создать конфиг в домашней директории проекта (но так, что бы не было доступно из Интернет). Пример конфигурационного файла приведён ниже:

source content
{
    # Тип данных
    # Доступные типы: mysql, pgsql, mssql, xmlpipe, xmlpipe2, odbc
    type		= mysql

    # Необходимые параметры для подключения к базе данных
    sql_host		= localhost
    sql_user		= dbuser
    sql_pass		= dbpass
    sql_db		= dbname
    sql_port		= 3306	# опциональный, по умолчанию 3306

    # пред-запрос, выполняется перед выполнением основного запроса на получение данных из базы
    # В нашей базе данные хранятся в UTF-8, чтобы поиск по русским символам работал успешно выполним соответсвующий запрос
    sql_query_pre	= SET NAMES utf8

    # запрос, который получает данные документов для поиска
    # первым полем обязательно должен идти уникальный положительный ID документа
    sql_query		= \
        SELECT id, guid, title, h1, content \
        FROM blogposts

    # поля, по которым может идти группировка, фильтрация и сортировка
    sql_attr_uint     = guid

    # document info query, ONLY for CLI search (ie. testing and debugging)
    # optional, default is empty
    # must contain $id macro and must fetch the document by that id
    sql_query_info	 = SELECT * FROM blogposts WHERE id=$id
}

# индекс по контенту
index content
{
     # Источник данных для индексирования
    source         = content

    # Адрес, где будут хранится данные индекса
    path           = /home/demo/sphinx/index/blogposts

    # Индекс с учетом морфологии
    morphology     = stem_enru

    # Минимальная длина слова для индексации
    min_word_len   = 2

    # Кодировка
    charset_type   = utf-8
    charset_table  = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F, U+401->U+451, U+451
    blend_chars    = &, ., +, U+23
    min_infix_len  = 2
    enable_star    = 1
    index_exact_words = 1
    html_strip     = 1
}

indexer
{
    mem_limit           = 64M
}

searchd
{
    listen		= 9312
    log			= /home/demo/sphinx/log/searchd.log
    query_log		= /home/demo/sphinx/log/query.log
    read_timeout	= 5
    max_children	= 30
    pid_file		= /home/demo/sphinx/log/searchd.pid
    max_matches		= 1000
    seamless_rotate	= 1
    preopen_indexes	= 1
    unlink_old		= 1
    workers		= threads # for RT to work
    binlog_path		= /home/demo/sphinx/log
}

Для создания индекса базы используется команда

indexer --config путь_до_файла_конфигурации

Если демон уже запущен, необходимо использовать опцию –rotate, в противном случае возможна ошибка при попытке пересоздания поискового индекса.

После того как индекс создан, можно произвести тестовый поиск:

search --config путь_до_файла_конфигурации поисковый_запрос

После того, как убедились, что поиск работает и сервер вернул результат, можно запустить поискового демона, который будет отвечать на запросы сделанные из PHP:

searchd --config путь_до_файла_конфигурации

Теперь приступим к тому, ради чего было проделано всё выше описанное: использование Sphinx API в PHP.

Скачиваем Sphinx API.

Для поиска воспользуемся следующим кодом:

$sphinx = new SphinxClient;
$sphinx->SetServer($host, $port);

$sphinx->open();
$sphinx->SetSortMode(SPH_SORT_RELEVANCE);
$sphinx->setFieldWeights(array(
	'title' => 10,
	'h1' => 5,
	'content' => 1,
));

$sphinx->setLimits(0, 1000, 1000);
$results = $sphinx->query($sphinx->escapeString($phrase), $index);

В переменной $results будут находиться результаты поиска.

При выводе можно генерировать сниппет с подсвеченными вхождениями искомой фразы:

$res = $sphinx->buildExcerpts($var, 'content', $phrase, array(
	'before_match' => '<strong>',
	'after_match' => '</strong>'
));

В $res будет содержаться сниппет.

Вот и всё, что хотелось рассказать. Дальше остаётся только экспериментировать с конфигурацией Sphinx. Более подробно о возможностях Sphinx можно почитать на официальном сайте.

blogposts