Интеграция Sphinx для поиска на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Интеграция Sphinx для поиска на сайте
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Интеграция Sphinx для поиска на сайте

Sphinx Search и его активно развиваемый форк Manticore Search — проверенные поисковые движки с многолетней историей в highload-проектах. Используются там, где важна совместимость с MySQL-протоколом, зрелость решения и прямой контроль над индексами. Manticore Search добавил поддержку JSON-документов, колоночного хранилища, HTTP API и RT-индексов реального времени.

Когда выбирают Sphinx / Manticore

  • Легаси-проекты с существующей Sphinx-инфраструктурой
  • Нужна MySQL-совместимость — подключение через стандартные MySQL-клиенты
  • Корпус в сотни миллионов документов: новостные агрегаторы, архивы
  • Полный контроль над токенизатором и морфологией
  • Интеграция с существующей MySQL/MariaDB-репликацией

Manticore Search vs Sphinx

Характеристика Sphinx 3.x Manticore Search 6.x
Разработка Замедлена Активная
RT-индексы Базовые Полноценные
JSON-документы Нет Да
HTTP API Нет Да (Elasticsearch-совместимый)
Колоночное хранилище Нет Да
MySQL-протокол Да Да

Для новых проектов предпочтительнее Manticore Search.

Установка Manticore Search

# docker-compose.yml
services:
  manticore:
    image: manticoresearch/manticore:6.2.12
    environment:
      - EXTRA=1
    ports:
      - "9306:9306"   # MySQL-совместимый порт
      - "9308:9308"   # HTTP API
    volumes:
      - manticore_data:/var/lib/manticore
      - ./manticore.conf:/etc/manticoresearch/manticore.conf

Конфигурация индекса

# manticore.conf
index articles {
    type         = rt
    path         = /var/lib/manticore/articles

    rt_field     = title
    rt_field     = body
    rt_field     = author

    rt_attr_uint   = category_id
    rt_attr_bigint = created_at
    rt_attr_float  = rating
    rt_attr_string = slug

    morphology     = stem_ru, stem_en
    min_word_len   = 2
    expand_keywords = 1
    min_infix_len  = 3
    stopwords      = /etc/manticoresearch/stopwords_ru.txt
}

searchd {
    listen       = 0.0.0.0:9306:mysql41
    listen       = 0.0.0.0:9308:http
    log          = /var/log/manticore/searchd.log
    query_log    = /var/log/manticore/query.log
    max_matches  = 10000
}

Подключение через MySQL-клиент (PHP)

Manticore принимает SQL на порту 9306 по MySQL-протоколу:

$pdo = new PDO('mysql:host=localhost;port=9306;charset=utf8', '', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

Вставка документа:

$stmt = $pdo->prepare("
    INSERT INTO articles (id, title, body, author, category_id, created_at, rating)
    VALUES (:id, :title, :body, :author, :category_id, :created_at, :rating)
");
$stmt->execute([
    'id'          => $article->id,
    'title'       => $article->title,
    'body'        => strip_tags($article->content),
    'author'      => $article->user->name,
    'category_id' => $article->category_id,
    'created_at'  => $article->created_at->timestamp,
    'rating'      => $article->rating,
]);

Полнотекстовый поиск с весами полей:

$stmt = $pdo->prepare("
    SELECT id, title, author, rating,
           WEIGHT() AS relevance
    FROM articles
    WHERE MATCH(:query)
      AND category_id = :category_id
    ORDER BY relevance DESC, rating DESC
    LIMIT :offset, :limit
    OPTION ranker=bm25, field_weights=(title=10, body=1, author=2)
");

HTTP API (Elasticsearch-совместимый)

# Индексация
curl -X POST 'http://localhost:9308/articles/_doc/1' \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Заголовок статьи",
    "body": "Текст статьи",
    "category_id": 5
  }'

# Полнотекстовый поиск
curl -X POST 'http://localhost:9308/articles/_search' \
  -H 'Content-Type: application/json' \
  -d '{
    "query": { "match": { "title": "поиск по сайту" } },
    "sort": [{ "_score": "desc" }],
    "size": 20
  }'

Синхронизация с основной БД

Batch-индексация через chunk:

public function handle(): void
{
    $pdo = $this->getManticoreConnection();

    Article::with('user', 'category')
        ->where('published', true)
        ->chunk(1000, function ($articles) use ($pdo) {
            $pdo->beginTransaction();
            foreach ($articles as $article) {
                $pdo->prepare("REPLACE INTO articles ...")->execute(
                    $this->toDocument($article)
                );
            }
            $pdo->commit();
        });
}

Event-driven обновление через Observer:

class ArticleObserver
{
    public function saved(Article $article): void
    {
        ManticoreIndexJob::dispatch($article->id);
    }

    public function deleted(Article $article): void
    {
        ManticoreDeleteJob::dispatch($article->id);
    }
}

Морфология русского языка

Sphinx/Manticore включает встроенный стеммер stem_ru. Для более точной морфологии используется morphology = lemmatize_ru_all — требует отдельных словарей lemmatize. Это позволяет находить «бегущий» по запросу «бег» и наоборот.

Стоп-слова подключаются файлом — список предлогов, союзов, частиц, которые исключаются из индекса.

Подсветка результатов

SELECT id, title,
       SNIPPET(body, :query,
               'limit=200, around=5, html_strip_mode=strip') AS excerpt
FROM articles
WHERE MATCH(:query)
LIMIT 20

SNIPPET() возвращает фрагмент текста с выделением найденных слов — готово для отображения в результатах поиска.

Сроки работ

Этап Время
Установка, конфигурация, схема индекса 1 день
Первичная индексация + синхронизатор 2 дня
API поиска в приложении + тесты 2 дня
UI: результаты, сниппеты, пагинация 1–2 дня

Итого: 6–7 рабочих дней.