Yii2 → Sphinx реализуем поиск по сайту

Задача: реализовать полнотекстовый поиск по сайту с помощью Sphinx.

1. Устанавливаем Sphinx

Устанавливаем через sudo apt-get install sphinxsearchлибо по инструкции из документации для вашей ОС.

Далее правим настройки поискового демона/etc/default/sphinxsearch изменяем на START=yes, для авто-запуска.

2. Настраиваем Sphinx и запускаем

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

        sql_query = \
                SELECT id, type_id, title, content \
                FROM table \
                WHERE id >= $start AND id <= $end
        sql_query_range = SELECT MIN(id),MAX(id) FROM file
        sql_attr_uint = type_id

Когда конфиг отредактирован и сохранен запускаем индексацию и стартуем поисковый демон:

indexer --all
searchd

Дальнейшую переиндексацию можно проводить с помощью команды indexer --rotate --all без перезапуска. Для периодической индексации новых материалов можно добавить задание в /etc/crontab:

*/30 * * * * /usr/bin/indexer --rotate --all > /dev/null 2>&1

В старых версиях проверить поиск можно было в консоли:
search -q поисковый запрос, в новых выпилили.

Известные ошибки

sphinx returned 0 matches of 0 total

Если при проверке sphinx не возвращает результатов на русском, убедитесь что в конфиге имеется строка sql_query_pre = SET NAMES utf8 которая задает кодировку подключения.

SQLSTATE[HY000] [2054] Server sent charset unknown to the client. Please, report to the developers

Проверьте какая версия Sphinx у вас. Если у вас релиз ниже r3340, например Sphinx 2.0.4-id64-release (r3135). То обновите версию Sphinx до последней актуальной. Ошибка исправлена в релизе r3340.

3. Работа с Sphinx в Yii2

Устанавливаем расширение через Composer

composer require --prefer-dist yiisoft/yii2-sphinx

Добавляем в конфигурацию:

return [
    //....
    'components' => [
        'sphinx' => [
            'class' => 'yii\sphinx\Connection',
            'dsn' => 'mysql:host=127.0.0.1;port=9306;',
            'username' => '',
            'password' => '',
        ],
    ],
];

В контроллере используем по аналогии с привычным компонентом Query:

use yii\sphinx\Query;

$query = new Query;
$rows = $query->from('index')
    ->match($_GET['поисковая строка'])
    ->all();

Где index —  поисковый индекс настроенный вами в конфигурации. Метод match() по умолчанию экранирует все спецсимволы. На выходе будет сформирован SQL-подобный запрос, содержащий конструкцию MATCH.

Резульатом мы получим массив с id, и другими атрибутами заданными в конфигурации sphinx, которые удовлетворяют нашему запросу.

Зачем нужно задавать атрибуты? По-умолчанию в сфинксе fulltext-поля хранить и получать не возможно (потому что они просто нигде не хранятся в виде полного значения). Sphinx возвращает не данные, а только ID найденных запиcей, после чего необходимо делать запрос к БД для получения записей по ID.

Если вам необходимо иметь возможность дополнительно производить фильтрацию по полям типа type_id или вы хотите выводить их без повторного обращения к БД, то вы можете указать их в виде атрибутов в конфигурации: sql_attr_uint, sql_attr_float, sql_attr_string и т.д.

Из источника:

The raw text of Fields is NOT stored, and can NOT be retrieved from the sphinx index. The text is broken into words, hashed, and stored in an inverted index.

Attributes are stored as is in the index. Because the content is stored, they can be used for filtering, sorting and grouping. Can also include the content of the attribute(s) in the result-set.

  • Сашка Маковкин

    Добрый день.
    пытаюсь разобраться с расширением и со sphinx в целом.
    установил sphinx. протестил через консоль. все хорошо.
    а вот когда уже на сайте запускаю, то вижу ошибку Can’t connect to MySQL server on ‘127.0.0.1’ (111)

    что это может быть?
    использую DigitalOcean + VestaCP

    **************************************************
    может кому поможет:

    решилось тем, что поигрался со статусами сфинкса. то остановил, то рестартнул. заменил права на один файлик. и все. теперь работает.