Установка и настройка поискового движка Sphinx

Sphinx — бесплатный поисковый движок. Он поможет создать быструю систему поиска информации по базе данных вашего сайта. Здесь мы рассмотрим работу Sphinx на примере взаимдействия с сайтом на Wordpress.

  • Шаг 1Подготовка

    Начнем с установки и настройки Sphinx. Для этого заходим в свой аккаунт через SSH удобным вам ssh-клиентом или через web-ssh в панели хостинга (инструкция по настройке беспарольного SSH-доступа на сервер здесь).

    Далее работаем через командную строку сервера на вашем аккаунте. Создаем папку, в которой будут исходные коды Sphinx:

    mkdir src

    Переходим в созданную папку:

    cd src

    Клонируем при помощи git ветку Sphinx из репозитория разработчиков:

    git clone https://github.com/sphinxsearch/sphinx.git

    Переходим в папку исходных кодов Sphinx:

    cd sphinx

    Конфигурируем компилятор с указанием папки вашего аккаунта, куда будет установлен Sphinx, а также параметрами, указывающими, что мы будем в работе со Sphinx использовать СУБД mysql, а данные могут быть в разных кодировках:

    ./configure --prefix=/home/hostXXXXXXX/sphinx/ --with-mysql --with-iconv

    hostXXXXXXX - заменяем на номер вашего аккаунта.

    Выполняем сборку Sphinx (это может занять некоторое время):

    make

    Выполняем установку Sphinx:

    make install

    В нашем примере Sphinx будет индексировать базу данных сайта, работающего на CMS WordPress. Мы это делаем только ради примера, вы же можете использовать Sphinx для индексации любых нужных вам текстовых данных. Соответственно, следующим шагом установим WordPress. Для этого в панели хостинга в разделе «Сайты» - «Автоустановка приложений» сформируем запрос на установку этой CMS на тестовый домен.

    Пока Wordpress устанавливается, в консоли вернемся в корневую папку аккаунта:

    cd ~

    Создаём несколько служебных папок для Sphinx:

    mkdir -p sphinx/log/
    mkdir -p sphinx/var/data/

    Создаём конфигурационный файл Sphinx и помещаем в него нужные вам настройки:

    nano sphinx/sphinx.conf
    #======================================
    source hostXXXXXXXX_XXXX {
    # Параметры подключения к БД, которые в нашем случае нужно взять из файла /hostXXXXXXX.hostland.pro/htdocs/www/wp-config.php
    type = mysql # тип базы данных
    sql_host = localhost # адрес сервера базы данных. В нашем случае всегда - localhost
    sql_db = hostXXXXXXXX_XXXX  # имя базы данных
    sql_user = hostXXXXXXXX_XXXX # имя пользователя БД
    sql_pass = XXXXXXXX # пароль к пользователю БД
    
    # Установим кодировку для работы с БД
    sql_query_pre = SET NAMES utf8
    sql_query_pre = SET CHARACTER SET utf8
    
    # Запрос выборки данных для индексации
    sql_query = SELECT ID as post_id, post_title, post_content FROM wp_posts WHERE post_type = 'post'
    
    # Время простоя (sleep) перед посылкой запросов серверу (предназначен для разгрузки сервера БД)
    # Если установите "= 1000", то засыпание будет длится 1 секунду
    sql_ranged_throttle = 100
    
    }
    
    index hostXXXXXXXX_XXXX { 
    # Использовать соответствующий source-блок настроек при индексации
    source = hostXXXXXXXX_XXXX  
    # Путь до файлов индекса
    path = /home/hostXXXXXXXX/sphinx/var/data/hostXXXXXXXX_XXXX-index 
    
    # Способ хранения индекса (none, inline, extern)
    # Подробнее http://sphinxsearch.com/docs/current.html#conf-docinfo
    docinfo = extern
    
    # Memory lock (http://sphinxsearch.com/docs/current.html#conf-mlock)
    mlock = 0
    
    # Использование английского и русского стемминга (http://sphinxsearch.com/docs/current.html#conf-morphology)
    morphology = stem_enru
    
    # Минимальная длина индексируемого слова
    min_word_len = 2
    
    # Установка используемой кодировки
    charset_type = utf-8
    
    # Таблица символов (http://sphinxsearch.com/docs/current.html#conf-charset-table)
    charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
    
    # Минимальная длина инфикса (префикс в том числе)
    min_infix_len = 2
    
    }
    
    indexer {
    
    # Максимальный лимит используемой памяти RAM
    mem_limit = 32M
    
    }
    
    searchd { 
    
    log = /home/hostXXXXXXXX/sphinx/log/searchd.log 
    query_log = /home/hostXXXXXXXX/sphinx/log/query.log
    pid_file = /home/hostXXXXXXXX/sphinx/searchd.pid 
    listen = /home/hostXXXXXXXX/sphinx/sphinx.sock
    
    #Таймаут на соединение с сервером (в секундах). При истечении времени происходит обрыв
    read_timeout = 5
    
    }
    #======================================

    Обратите внимание: работать Sphinx будет через сокет. Поэтому в переменной listen в конфиге указан именно сокет, а не порт. Это важно, т.к. в рамках виртуального хостинга, чтобы не возникало конфликтов с другими Sphinx, работающими у других пользователей сервера, мы отказываемся от работы через порты. Файл сокета лежит внутри вашего аккаунта и никому более недоступен. Это безопасно.

  • Шаг 2Индексация данных

    Теперь вернёмся к WordPress. Чтобы Sphinx мог индексировать какие-то данные из него, этими данными его нужно заполнить. Для этого сначала скачаем данный файл на своё устройство (если с github скачивание недоступно, то копия файла здесь). Этот файл содержит набор демо-данных для WordPress, которые позволят быстро наполнить базу CMS различной тестовой информацией. Таким образом в нашем примере мы получим сайт на WordPress с наполнением, которое можно будет проиндексировать при помощи Sphinx.

    Далее зайдем в Wordpress, используя данные, которые прислал на нашу контактную почту сервис установки приложений. Переходим в раздел «Инструменты» -> «Импорт». Нажимаем кнопку «Установить» под модулем «WordPress».

    После того, как модуль будет установлен, нажимаем кнопку «Запустить импорт». В появившейся форме нажимаем кнопку «Обзор» и выбираем ранее скачанный файл themeunittestdata.wordpress.xml. Далее нажимаем "Запустить и импортировать файл".

    В процессе импорта Wordpress запросит у вас некоторые данные. Нужно будет выбрать пользователя, от имени которого будут импортированы демо-данные. Везде выбирайте пользователя admin, чтобы не тратить время на создание нового. Также, установите флаг напротив пункта «Скачать и импортировать файлы вложений».

    Как только импорт будет закончен, сайт будет наполнен различными записями с текстом и картинками, также будут добавлены рубрики, метки, страницы и комментарии. С таким наполнением уже можно работать через Sphinx. Возвращаемся в командную строку сервера на аккаунте.

    Запускаем Sphinx:

    cd ~ && ./sphinx/bin/searchd -c ./sphinx/sphinx.conf

    Выполняем индексацию базы:

    cd ~ && ./sphinx/bin/indexer -c sphinx/sphinx.conf --rotate --all

    Sphinx запущен и работает. Проверить можно, запустив команду:

    ps aux | grep sphinx | grep -v grep

    В результате, сервер должен показать как минимум один процесс, запущенный от имени вашего аккаунта:

  • Шаг 3Работа со Sphinx

    Теперь, для работы c индексом, созданным Sphinx, создадим php-скрипт с простым html-интерфейсом. А поскольку взаимодействие php-скрипта со Sphinx в нашем случае будет происходить через Sphinx API для PHP, то предварительно скопируем файл api из скачанного ранее дистрибутива Sphinx в рабочую папку нашего скрипта через серверную командную строку аккаунта:

    cp ~/src/sphinx/api/sphinxapi.php ~/hostXXXXXXXX.hostland.pro/htdocs/test/

    Затем в этот файл нужно внести некоторые правки:

    sed -i "778d" ~/hostXXXXXXXX.hostland.pro/htdocs/test/sphinxapi.php

    Далее создаём сам php-скрипт. Сделать это можно через «Файловый менеджер» в панели аккаунта. Пройдём в папку /hostXXXXXXXX.hostland.pro/htcdocs/test/. В ней создадим файл index.php и положим в него следующее содержимое:

    <html>
    <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
        <title>Поиск по сайту на CMS Wordpress через Sphinx</title>
    </head>
    <body>
    
    <form action="" method="get">
        <input name="s" size="40" value="<?php echo @$_GET['s'];?>" />
        <input type="submit" value="искать" />
    </form>
    <?php
    if(isset($_GET['s']) and strlen($_GET['s']) > 2) {
    
        // Подключаем API
        require_once ("sphinxapi.php");
    
        // Фраза для поиска
        $string = $_GET['s'];
    
        // Создаем объект клиента для Sphinx API
        $sphinx = new SphinxClient();
    
        // Подключаемся к Sphinx-серверу чепез сокет
        $sphinx->SetServer('/home/hostXXXXXXXX/sphinx/sphinx.sock');
    
        // Режим поиска - совпадение по любому слову
        $sphinx->SetMatchMode(SPH_MATCH_ANY);
    
        // Режим сортировки результаов - по релевантности
        $sphinx->SetSortMode(SPH_SORT_RELEVANCE);
    
        // Задаем полям вес (для подсчета релевантности)
        $sphinx->SetFieldWeights(array ('post_title' => 20, 'post_content' => 10));
    
        // Результат по запросу (* - использование всех индексов)
        $result = $sphinx->Query($string, '*');
    
        // Если есть результаты поиска, то отрисовываем их на странице
        if ($result && isset($result['matches']))
        {
    
            // Подключение к БД
            $link = mysqli_connect('localhost', 'hostXXXXXXXX_XXXX', 'XXXXXXXX', 'hostXXXXXXXXXXXX');
    
            // Массив ID постов блога в переменную
            $ids = array_keys($result['matches']);
    
            // Вывод постов по релевантности
            $id_list = implode(',', $ids);
            $sql = 'SELECT `ID`, `post_title`, `post_content` FROM `wp_posts` WHERE `ID` IN ('.$id_list.') ORDER BY FIELD(`ID`, '.$id_list.')';
    
            // Непосредственно запрос к БД
            $resource = mysqli_query($link, $sql);
    
            // Выводим результаты поиска
            echo '<ol>';
            while ($result = mysqli_fetch_assoc($resource)) {
                echo '<li><span><a href="/?p='.$result['ID'].'">'.$result['post_title'].'</a></span><div>'.mb_substr(htmlspecialchars($result['post_content']), 0, 400).'</div>';
            }
            echo '</ol>';
        }
    }
    ?>
    </body>
    </html>

    Проверяем работу нашего скрипта. Открываем в браузере: http://test.hostXXXXXXXX.hostland.pro/, в форме поиска вводим, например, слово "Sticky" и нажимаем кнопку «искать». Получаем такой результат поиска:

    Далее создадим скрипт, который будет проверять, работает ли Sphinx. А если не работает, то запускает его. Также скрипт будет выполнять переиндексацию базы. Скрипт будем запускать через планировщик cron раз в 10 минут. Таким образом будем поддерживать актуальность индекса и работоспособность самого Sphinx.

    nano ~/sphinxreload.sh
    #!/bin/bash 
           comm=$(ps aux | grep searchd | grep -v grep | wc -l) 
           if [ "$comm" -eq 0 ] 
    then { 
           cd ~ && ./sphinx/bin/searchd -c ./sphinx/sphinx.conf
           exit 1 
    } 
    fi;
    
    cd ~ && ./sphinx/bin/indexer -c sphinx/sphinx.conf --rotate --all

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

    chmod +x ~/sphinxreload.sh

    Добавляем созданный скрипт в «Планировщик задач (Cron)» через панель хостинга на запуск раз в 10 минут. Для этого нажимаем кнопку «Создать cron-задание». Переходим во вкладку «Задать вручную» и прописываем в поле «Команда» следующее:

    */10 * * * * cd /home/hostXXXXXXXX/ && ./sphinxreload.sh

    Нажимаем кнопку «Создать задание».

Удачной работы! Если возникнут вопросы - напишите нам, пожалуйста, тикет из панели управления хостингом, раздел «Помощь и поддержка».