Тест на вакансию

Установка, настройка и работа с Manticore Search в Docker-контейнере

27 ноября 2025 г.
196

Структура

Создаём следующую структуру:
  • docker-compose.yml
  • manticore/
    • config/
      • manticore.conf
    • data/
    • log/
    • run/

Docker Compose файл

Напишем следующий docker-compose.yml:
services:
  manticore:
    image: manticoresearch/manticore:latest
    container_name: manticore-search
    ports:
      - "9306:9306"  # MySQL protocol
      - "9308:9308"  # HTTP protocol
      - "9312:9312"  # Binary protocol
    volumes:
      - ./manticore/data:/var/lib/manticore
      - ./manticore/log:/var/log/manticore
      - ./manticore/config/manticore.conf:/etc/manticoresearch/manticore.conf
      - ./manticore/run:/var/run/manticore
    environment:
      - EXTRA=1
    ulimits:
      nproc: 65535
      nofile:
        soft: 65535
        hard: 65535
    restart: unless-stopped
    networks:
      - manticore-net
networks:
  manticore-net:
    driver: bridge

Базовая настройка

Основной конфигурационный файл (/etc/manticoresearch/manticore.conf)
searchd {
    listen = 0.0.0.0:9312
    listen = 0.0.0.0:9306:mysql
    listen = 0.0.0.0:9308:http
    log = /var/log/manticore/searchd.log
    query_log = /var/log/manticore/query.log
    pid_file = /var/run/manticore/searchd.pid
    query_log_format = sphinxql
}
indexer {
    mem_limit = 128M
}
common {
    plugin_dir = /usr/lib/manticore
}
Далее можно сделать запуск контейнера:
docker-compose up -d

Создание индексов и заполнение данными

Конфигурация индекса (добавим в manticore.conf):

index products {
    type = rt
    path = /var/lib/manticore/products
    
    rt_field = title
    rt_field = description
    rt_attr_string = category
    rt_attr_uint = price
    rt_attr_timestamp = created_at
    rt_attr_multi = tags
    
    min_infix_len = 3
    expand_keywords = 1
}

И сделаем перезапуск контейнера:
docker-compose restart

Заполнение данными через MySQL протокол

Подключение:
mysql -P 9306 -h 127.0.0.1
Вставка данных:
INSERT INTO products (id, title, description, category, price, created_at, tags) 
VALUES 
(1, 'Смартфон Samsung Galaxy', 'Новый флагманский смартфон с отличной камерой', 'electronics', 59990, 1701388800, (1, 2, 3)),
(2, 'Ноутбук ASUS ZenBook', 'Ультрабук с процессором Intel Core i7', 'computers', 89990, 1701388800, (4, 5)),
(3, 'Наушники Sony WH-1000XM4', 'Беспроводные наушники с шумоподавлением', 'audio', 24990, 1701388800, (6, 7));
Пакетная вставка:
INSERT INTO products (id, title, description, category, price, tags) VALUES
(4, 'Мышь Logitech MX Master', 'Эргономичная беспроводная мышь', 'computers', 8990, (8)),
(5, 'Клавиатура Mechanical', 'Механическая клавиатура с RGB подсветкой', 'computers', 12990, (9, 10));

Заполнение через HTTP API

Вставка одной записи:
curl -X POST http://localhost:9308/json/insert \
  -H "Content-Type: application/json" \
  -d '{
    "index":"products",
    "id": 6,
    "doc": {
        "title": "Планшет Apple iPad Air",
        "description": "Мощный планшет для работы и творчества",
        "category": "tablets",
        "price": 54990,
        "tags": [11, 12]
    }
}'

Пакетная вставка:
curl -X POST http://localhost:9308/json/bulk \
  -H "Content-Type: application/x-ndjson" \
  -d '
{"insert": {"index":"products", "id":7, "doc": {"title":"Фотокамера Canon EOS", "category":"photo", "price":45990}}}
{"insert": {"index":"products", "id":8, "doc": {"title":"Телевизор LG OLED", "category":"tv", "price":129990}}}
'

Создание индекса из MySQL базы данных

Конфигурация источника данных:
source products_source {
    type = mysql
    sql_host = localhost
    sql_user = username
    sql_pass = password
    sql_db = ecommerce
    sql_query = SELECT id, title, description, category, price, UNIX_TIMESTAMP(created_at) as created_at FROM products

    sql_attr_uint = group_id
    sql_attr_string = category
    sql_attr_uint = price
    sql_attr_timestamp = created_at

    sql_field_string = title
    sql_field_string = description
}

index products_main {
    source = products_source
    path = /var/lib/manticore/products_main

    min_word_len = 3
    min_infix_len = 3
    expand_keywords = 1
}
Где:
  • min_word_len = 3 - Определяет минимальную длину слова для индексации.
  • min_infix_len = 3 - Минимальная длина префикса/инфикса для поиска (позволяет искать по первым 3+ символам).
  • expand_keywords = 1 - Расширяет ключевые слова при поиске (пользователь ищет: "тест", система ищет: "тест*").
Индексация данных:
sudo -u manticore indexer --all --rotate
Далее возможно необходима перезагрузка контейнера:
docker-compose restart

Примеры поисковых запросов

Через MySQL протокол

Простой поиск:
SELECT * FROM products WHERE MATCH('смартфон');
Поиск с фильтрацией:
SELECT * FROM products 
WHERE MATCH('ноутбук') AND category = 'computers' AND price < 100000;
Поиск с сортировкой:
SELECT * FROM products 
WHERE MATCH('беспроводные') 
ORDER BY price DESC 
LIMIT 10;
Агрегационные запросы:
SELECT category, COUNT(*), AVG(price) 
FROM products 
GROUP BY category;

Через HTTP API

Простой поиск:
curl -X POST http://localhost:9308/search \
  -H "Content-Type: application/json" \
  -d '
{
    "index": "products",
    "query": {
        "match": {
            "title": "смартфон"
        }
    },
    "limit": 10
}'
Поиск с фильтрами:
curl -X POST http://localhost:9308/search \
  -H "Content-Type: application/json" \
  -d '
{
    "index": "products",
    "query": {
        "bool": {
            "must": [
                {"match": {"title": "ноутбук"}}
            ],
            "filter": [
                {"range": {"price": {"lte": 100000}}}
            ]
        }
    }
}'

Полезные команды для управления

Получение схемы индекса:
mysql -P 9306 -e "DESCRIBE products"
Информация о количестве документов, размере и показателях производительности:
mysql -P 9306 -e "SHOW INDEX products STATUS"
Оптимизация индекса:
mysql -P 9306 -e "OPTIMIZE INDEX products"
Получение информации об индексе:
mysql -P 9306 -e "DESC products"
mysql -P 9306 -e "SHOW META"

Базовая оптимизация

searchd {
    # ... остальные настройки ...
    max_children = 100
    max_packet_size = 128M
    workers = threads
    binlog_path = /var/lib/manticore
}

index products {
    # ... остальные настройки ...
    morphology = stem_ru, stem_en
    stopwords = /etc/manticoresearch/stopwords.txt
    min_word_len = 2
}
  • max_children = 100 - Ограничивает максимальное количество одновременных соединений к серверу
  • max_packet_size = 128M - Увеличивает максимальный размер пакета данных
  • workers = threads - Использует потоки (threads) вместо процессов (fork) для обработки запросов
  • binlog_path = /var/lib/manticore - Включает бинарное логирование и указывает путь для файлов бинарного лога
  • morphology = stem_ru, stem_en - Включает морфологическую обработку для русского и английского языков ("смартфоны" → "смартфон", "running" → "run")
  • stopwords = /etc/manticoresearch/stopwords.txt - Загружает стоп-слова из файла (Примеры для русского: "и", "в", "на", "с", "по")
  • min_word_len = 2 - Минимальная длина слова для индексации
Поделиться: