# Meilisearch и Manticore Search: проверяем сравнение на практике

Meilisearch опубликовал сравнение с Manticore Search. Мы проверили его выводы на актуальных версиях обоих движков и приводим команды, чтобы результаты можно было воспроизвести.

Несколько дней назад Meilisearch опубликовал [сравнение с Manticore Search](https://www.meilisearch.com/blog/meilisearch-vs-manticore). Мы тоже любим сравнения: в 2023 году [опубликовали своё](/blog/manticoresearch-vs-meilisearch/) с воспроизводимыми бенчмарками. Сразу оговоримся: мы спорим не со всей статьёй. Часть выводов Meilisearch справедлива, а кое-где сравнение говорит в пользу Manticore Search.

Однако часть сведений о Manticore Search уже устарела. Спорить в теории мы не стали: запустили актуальные версии обоих движков (Manticore Search 28.4.4 и Meilisearch 1.41/1.48) и повторили описанные сценарии. Ниже мы приводим команды и ответы обоих движков, чтобы проверку можно было повторить самостоятельно.

## «Полнотекстовый поиск и аналитика в реальном времени» — лишь часть возможностей Manticore Search

В статье Manticore Search представлен так:

> Manticore Search — поисковый движок с открытым исходным кодом, созданный как продолжение Sphinx. Он расширяет возможности Sphinx, добавляя полнотекстовый поиск и аналитику в реальном времени.

Полнотекстовый поиск был уже в Sphinx, а аналитика в реальном времени — лишь одна из возможностей, появившихся с тех пор. Вот что ещё добавилось за годы развития:

- **[RT-режим](/blog/rt_vs_plain_mode/)** — Sphinx уже поддерживал RT-индексы, но сегодня весь движок может работать без конфигурационных файлов: таблицы создаются через `CREATE TABLE`, а вставка и поиск доступны сразу
- **[Репликация](/blog/mike-replication/)** — синхронная кластерная репликация на базе Galera
- **Полноценный HTTP JSON API** — почти все возможности SQL, а также совместимые с Elasticsearch эндпоинты для пакетной загрузки
- **[Автосхема](/blog/create_table/)** — данные можно вставлять, не создавая таблицу заранее
- **[Векторный поиск](/blog/vector-search-deep-dive/)** с [автоэмбеддингами](/blog/auto-embeddings/), [квантованием](/blog/quantization/) и [предварительной фильтрацией KNN](/blog/knn-prefiltering/)
- **[Гибридный поиск](/blog/hybrid-search/)** — результаты полнотекстового и семантического поиска объединяются методом Reciprocal Rank Fusion в одном запросе
- **[Нечёткий поиск](/blog/new-fuzzy-search-and-autocomplete/) и [автодополнение](/blog/autocomplete-the-predictive-search/)** — исправление опечаток, учёт раскладки клавиатуры и поисковые подсказки
- **[Колоночное хранилище](/blog/mcl/) и вторичные индексы** — для данных, которые не помещаются в оперативную память
- **[Шардированные таблицы, аутентификация и диалоговый поиск](/blog/manticore-search-27-1-5/)**
- **[Интеграция с Kafka](/blog/integration-with-kafka/)**, поддержка [Kibana](/blog/kibana-demo/) и [Grafana](/blog/grafana-dashboard-docker/), а также [MCP-сервер](/blog/mcp-manticore-server/) для ИИ-ассистентов

Поэтому описание Manticore Search как «Sphinx с аналитикой в реальном времени» давно не отражает возможностей движка.

## «Сложная настройка» и «глубокая кастомизация»: проверим на практике

В статье Manticore Search описывают так:

> Лучше всего подходит крупным проектам и командам, которым нужны гибкая настройка, знание SQL и высокая производительность на больших объёмах данных.

В списке недостатков также указано: «Сложная настройка: первоначальная конфигурация и тюнинг могут занять много времени».

Однако для первого поиска в Manticore Search достаточно трёх команд. Отдельный конфигурационный файл и заранее описанная схема не нужны:

**1. Установите Manticore Search. [Однострочный установщик](/blog/one-line-installer/) сразу запустит сервис:**

```bash
curl https://manticoresearch.com | sh
```

**2. Добавьте документ. Таблицу заранее создавать не нужно: [автосхема](/blog/create_table/) определит её по данным:**

```bash
curl -s 0:9308/insert -d '{
  "table": "products",
  "doc": {"title": "yellow travel backpack", "price": 4990, "color": "yellow"}
}' | jq
```

```json
{
  "table": "products",
  "id": 8938969113712132097,
  "created": true,
  "result": "created",
  "status": 201
}
```

**3. Выполните полнотекстовый поиск и сразу отфильтруйте товары по цене:**

```bash
curl -s 0:9308/search -d '{
  "table": "products",
  "query": {"bool": {"must": [
    {"match": {"*": "backpack"}},
    {"range": {"price": {"lt": 6000}}}
  ]}}
}' | jq
```

```json
{
  "took": 0,
  "timed_out": false,
  "hits": {
    "total": 1,
    "total_relation": "eq",
    "hits": [
      {
        "_id": 8938969113712132097,
        "_score": 1356,
        "_source": {
          "title": "yellow travel backpack",
          "color": "yellow",
          "price": 4990
        }
      }
    ]
  }
}
```

После вставки документ сразу попадает в поиск. Полнотекстовый запрос можно ограничить конкретным полем, например `{"match": {"color": "yellow"}}`. По числовым атрибутам вроде `price` можно фильтровать, сортировать и группировать результаты, а также выполнять фасетный поиск без дополнительного объявления полей и переиндексации. Manticore Search автоматически определил следующую схему:

```
+-------+--------+----------------+
| Field | Type   | Properties     |
+-------+--------+----------------+
| id    | bigint |                |
| title | text   | indexed stored |
| color | text   | indexed stored |
| price | uint   |                |
+-------+--------+----------------+
```

Мы повторили этот сценарий в Meilisearch с Docker-тегом `latest`, версией 1.41.0 и текущим релизом 1.48.3. Установщик кладёт исполняемый файл в текущий каталог, но запускать его нужно отдельно. Чтобы запустить Meilisearch в рабочем режиме, сначала потребуется задать мастер-ключ. Добавление документов и обычный поиск устроены так же просто, как в Manticore Search. Однако фильтрацию необходимо настроить заранее — без этого запрос завершается ошибкой:

```bash
curl -s -X POST localhost:7700/indexes/products/search -H "Content-Type: application/json" \
  -d '{"q": "backpack", "filter": "price < 6000"}' | jq
```

```json
{
  "message": "Index `products`: Attribute `price` is not filterable. This index does not have configured filterable attributes.",
  "code": "invalid_search_filter",
  "type": "invalid_request"
}
```

Ниже — результаты проверки на актуальной версии Meilisearch. Каждый пункт мы также сверили с документацией:

- **Полнотекстовый поиск не требует предварительной настройки.** По умолчанию в `searchableAttributes` указано `["*"]`, поэтому поиск выполняется по всем полям документов.
- **Для фильтрации поля нужно заранее добавить в `filterableAttributes`.** [Документация Meilisearch](https://www.meilisearch.com/docs/learn/filtering_and_sorting/filter_search_results) прямо предупреждает о последствиях: *«Этот шаг обязателен и не может быть выполнен во время поиска. … Обновление `filterableAttributes` требует, чтобы Meilisearch переиндексировал все ваши данные, а это займёт время, пропорциональное размеру и сложности набора данных».*
- **Фасеты используют тот же список `filterableAttributes`.** Поэтому для них также необходимы предварительная настройка и переиндексация. В Manticore Search [фасетный поиск не требует ручной настройки фильтров](/blog/faceted-search-without-manual-filter-building/).
- **Поля сортировки тоже задаются отдельно.** [В документации Meilisearch](https://www.meilisearch.com/docs/learn/filtering_and_sorting/sort_search_results) сказано: *«Чтобы пользователи могли сортировать результаты во время поиска, необходимо … добавить эти атрибуты в настройку индекса `sortableAttributes`».*
- **Если изменить набор или порядок поисковых полей, Meilisearch тоже переиндексирует все документы.** Порядок `searchableAttributes` влияет на релевантность, и на практике эту настройку часто приходится менять. В документации это сформулировано прямо: *«Обновление `searchableAttributes` запускает переиндексацию всех документов в индексе».*

Это не ошибка, а архитектурное решение Meilisearch. Всё это настраивается простыми API-запросами, однако изменение списка фильтруемых, сортируемых или поисковых полей приводит к переиндексации всего набора данных. В Manticore Search тип поля сразу определяет, что с ним можно делать. Текстовые поля индексируются для полнотекстового поиска; числа, строки и JSON можно фильтровать, сортировать, группировать и использовать в фасетах; векторные поля доступны для KNN-поиска. Отдельного списка разрешённых операций для каждого поля нет. Ранжирование, токенизацию, морфологию и веса полей при необходимости можно настроить дополнительно, но это не обязательное условие работы с Manticore Search.

## SQL знать необязательно

Статья рекомендует Manticore Search командам, знакомым с SQL. SQL — действительно одна из сильных сторон движка: с Manticore Search можно работать через клиенты MySQL, `mysqldump` и BI-инструменты. В таблице интеграций из статьи такая возможность для Meilisearch отмечена как «Not supported».

Однако для всего примера выше хватило HTTP JSON API. Почти все операции Manticore Search доступны и через SQL, и через JSON. Последний хорошо знаком пользователям Meilisearch и Elasticsearch, поэтому для начала работы знание SQL не требуется.

## Векторный поиск: здесь наши оценки совпадают

В таблице сценариев Meilisearch так оценивает векторный поиск в обоих движках:

> **Векторный поиск.** Meilisearch: базовый векторный поиск. Manticore Search: лучше подходит для гибридных и сложных сценариев.

С этой оценкой мы согласны. Manticore Search [строит эмбеддинги сам](/blog/auto-embeddings/): не нужно выносить эту работу во внешний сервис или заводить API-ключи, а модель загрузится автоматически.

```sql
CREATE TABLE products_ai (
  title TEXT,
  description TEXT,
  price INT,
  vector FLOAT_VECTOR KNN_TYPE='hnsw' HNSW_SIMILARITY='l2'
    MODEL_NAME='sentence-transformers/all-MiniLM-L6-v2'
    FROM='title,description'
);
```

Документы можно отправлять в формате JSON: Manticore Search построит эмбеддинги автоматически. Для пакетной загрузки предусмотрен эндпоинт `/bulk`:

```bash
curl -s 0:9308/insert -d '{
  "table": "products_ai",
  "id": 1,
  "doc": {
    "title": "green hiking backpack",
    "description": "Lightweight backpack suitable for hiking trails",
    "price": 5999
  }
}'

curl -s 0:9308/insert -d '{
  "table": "products_ai",
  "id": 3,
  "doc": {
    "title": "trail running shoes",
    "description": "Lightweight shoes with great grip for trails",
    "price": 7500
  }
}'
```

Теперь выполним [полнотекстовый и семантический поиск](/blog/hybrid-search/) одним запросом и объединим выдачу с помощью RRF:

```bash
curl -s 0:9308/search -d '{
  "table": "products_ai",
  "hybrid": {"query": "gear for a mountain hike"},
  "_source": ["title", "price"],
  "size": 2
}' | jq
```

```json
{
  "hits": {
    "hits": [
      {
        "_id": 1,
        "_knn_dist": 0.88308269,
        "_hybrid_score": 0.01639344,
        "_source": {
          "title": "green hiking backpack",
          "price": 5999
        }
      },
      {
        "_id": 3,
        "_knn_dist": 1.09160841,
        "_hybrid_score": 0.01612903,
        "_source": {
          "title": "trail running shoes",
          "price": 7500
        }
      }
    ]
  }
}
```

В запросе есть слова `gear` и `mountain`, которых нет ни в одном документе, однако семантический поиск всё равно находит подходящие результаты. Расход оперативной памяти можно снизить с помощью [квантования векторов](/blog/quantization/), а при [предварительной фильтрации KNN](/blog/knn-prefiltering/) условия применяются во время обхода HNSW. Производительность KNN мы также [регулярно оптимизируем](/blog/knn-hnsw-performance/).

Попробовать эти функции можно в трёх демо Manticore Search: [поиске по каталогу](https://catalog.manticoresearch.com/) с фильтрами, фасетами, исправлением опечаток и семантическим поиском, [обратном поиске по изображениям](https://image.manticoresearch.com/) и [диалоговом поиске](https://chat.manticoresearch.com/).

## Релевантность: сравниваем по результатам тестов

Качество поиска можно измерить. Мы сравнили полнотекстовый, векторный и гибридный поиск Manticore Search и Meilisearch в 14 группах тестов на общедоступных наборах данных. В тесты вошли семь наборов BEIR, ACORD, TREC DL 2019 и 2020, товарный набор Wayfair WANDS и DL-Typo с опечатками в запросах. MS MARCO Passage проверяли на корпусах из 250 тыс. и 8,8 млн документов. В каждой группе выбирали лучший успешно завершившийся запуск для каждой пары «движок — режим». Затем по выбранным результатам считали невзвешенное среднее. Первая строка таблицы показывает среднее, рассчитанное по лучшему режиму каждого движка в каждой группе. В векторных и гибридных тестах мы использовали для обоих движков одну и ту же модель — Qwen3-Embedding-8B. Качество оценивали по стандартной для соответствующего набора метрике: NDCG@10, а для MS MARCO — MRR@10.

| Режим | Manticore | Meilisearch |
|---|---:|---:|
| Лучший режим для каждого датасета (среднее) | **0.543** | 0.527 |
| Векторный | **0.530** | 0.527 |
| Гибридный | **0.515** | 0.475 |
| Полнотекстовый | **0.420** | 0.237 |

Если для каждой группы брать лучший результат движка, Manticore Search лидирует в 11 из 14 групп. Качество векторного поиска почти одинаковое: 0,530 и 0,527. В обоих движках мы использовали одну и ту же модель эмбеддингов, хотя способы индексации и поиска у них различаются. В гибридном режиме разница заметнее: средний результат RRF у Manticore Search составляет 0,515 против 0,475 у Meilisearch.

Наибольшая разница наблюдается в полнотекстовом поиске: 0,420 против 0,237. Это согласуется с остальными результатами теста: движки с BM25 или близкими алгоритмами ранжирования заметно опережают Meilisearch. [Meilisearch использует другой подход](https://www.meilisearch.com/docs/learn/relevancy/ranking_rules): последовательно применяет правила, основанные на совпадении слов, опечатках, близости слов, атрибутах и точности совпадения. В отличие от BM25, этот подход не сочетает обратную частоту документа, насыщение частоты термина и нормализацию по длине документа. Этим во многом объясняются более слабые результаты Meilisearch на стандартных поисковых датасетах. Похожую картину показывает Typesense — ещё один движок из расширенного сравнения, который не использует BM25. Кроме того, Meilisearch учитывает только первые десять слов запроса, поэтому качество длинных запросов может снижаться.

Manticore Search также лидирует на DL-Typo — наборе данных, предназначенном для оценки поиска по запросам с опечатками.

По той же методике тестировались Elasticsearch, OpenSearch, Qdrant, Typesense, Vespa и Weaviate. Некоторые движки не завершили самые крупные тесты при доступных ресурсах, поэтому в отчёте отдельно приведены два рейтинга. В рейтинге по десяти группам, общим для всех восьми движков, Manticore Search занимает второе место после Qdrant. Если учитывать все 14 групп, он также занимает второе место среди пяти движков, прошедших их полностью. Средний результат Meilisearch ниже в обоих случаях.

В [полном сравнении](https://gist.github.com/manticoresearch/7c9b5d85ca8a62ce0066db6f0e17a11a) уже опубликованы результаты по каждому набору данных и точные конфигурации запусков. Исследование ещё продолжается: мы готовим подробное описание методики и оставшиеся материалы. Исходный код нового инструмента для бенчмарков тоже будет открыт, чтобы такие тесты было проще запускать и дополнять.

## Manticore Search используют не только в крупных проектах

В статье сказано:

> Manticore в основном используют для сложных задач поиска и аналитики на больших объёмах данных, где нужны высокая производительность и глубокая кастомизация.

В таблице сценариев также сказано, что Manticore «может быть избыточным для простых CMS-задач».

Мы сверились с [анонимизированной телеметрией](https://manual.manticoresearch.com/Telemetry). Среди установок Manticore Search, которые передают метрики объёма данных:

- **29%** хранят менее **1 МБ** данных
- около **половины** — менее **100 МБ**
- лишь примерно в **каждой восьмой** хранится более **10 ГБ** данных, а более **1 ТБ** — менее чем в **1%** установок

Телеметрия не подтверждает, что Manticore Search разворачивают преимущественно в высоконагруженных системах. Большинство установок обслуживают небольшие сайты, каталоги, блоги и внутренние системы — те самые «простые CMS-задачи» из сравнительной таблицы. Контейнер Manticore Search в простое потребляет менее 200 МБ оперативной памяти, а первый рабочий поиск запускается тремя командами. Для небольшого проекта это вряд ли можно назвать избыточным решением.

При этом Manticore Search подходит и для систем с высокой нагрузкой. Например, после миграции с Elasticsearch [одна из установок стала локально обслуживать десятки тысяч запросов в секунду](/blog/manticore-search-at-scale-on-google-cloud/). Небольшой объём данных не мешает системе выдерживать высокую нагрузку.

## Аналитика в реальном времени — важный, но не основной сценарий

В этой части таблица, напротив, сужает область применения Manticore Search: «Создан для данных и аналитики в реальном времени». Движок поддерживает [колоночное хранилище](/blog/mcl/), агрегации и интеграции с [Kibana](/blog/kibana-demo/), [Grafana](/blog/grafana-dashboard-docker/) и [системами сбора и обработки логов](/blog/integration-of-manticore-with-logstash-filebeat/), поэтому [подходит для поиска по логам](/blog/kibana-demo/). Тем не менее основная задача Manticore Search — поиск, а аналитика остаётся одним из дополнительных сценариев.

## С чем в статье Meilisearch можно согласиться

Для полноты отметим и те пункты, с которыми мы согласны:

- **Работа с опечатками по умолчанию.** В Meilisearch она включена сразу. В Manticore Search [нечёткий поиск](/blog/new-fuzzy-search-and-autocomplete/) включается отдельно: в определении таблицы нужно задать `min_infix_len='2'`, а в запросе — `fuzzy=1`. Для Manticore Search нужны две настройки; в Meilisearch этот сценарий работает без них.
- **Поиск прямо из фронтенда.** Ключи API для поиска в Meilisearch позволяют выполнять запросы без отдельного бэкенда. Manticore Search обычно разворачивают за серверным приложением; [аутентификация появилась в версии 27.1.5](/blog/manticore-search-27-1-5/), но сейчас Meilisearch лучше приспособлен к такому сценарию.
- **Пробелы в документации.** Они есть и у нас, и у Meilisearch. Но с формулировкой «высокий порог входа» мы не согласны: для начала достаточно базовых знаний SQL или JSON, а на [бесплатных интерактивных курсах](https://play.manticoresearch.com/) можно пройти весь путь — от создания первой таблицы до векторного поиска.

## Клиентские библиотеки: исправленная таблица

В [исходной сравнительной таблице Meilisearch](https://www.meilisearch.com/blog/meilisearch-vs-manticore) Go указан дважды, причём сведения в двух строках противоречат друг другу. Кроме того, для нескольких клиентов неверно указано, какие из них официальные, а какие поддерживаются сообществом; два языка не упомянуты вовсе. Ниже приведена исправленная версия, сверенная с [документацией SDK Meilisearch](https://www.meilisearch.com/docs/learn/resources/sdks) и [репозиториями Manticore Search на GitHub](https://github.com/manticoresoftware):

| Интеграция | Meilisearch | Manticore Search |
|---|---|---|
| JavaScript (Node.js) | Официальный клиент, написанный на TypeScript | [Официальный JavaScript-клиент](https://github.com/manticoresoftware/manticoresearch-javascript) |
| TypeScript † | Тот же официальный клиент на TypeScript | [Официальный TypeScript-клиент](https://github.com/manticoresoftware/manticoresearch-typescript) |
| Python | Официальный клиент с синхронным и асинхронным интерфейсами | Официальные клиенты: [синхронный](https://github.com/manticoresoftware/manticoresearch-python) и [асинхронный на asyncio](https://github.com/manticoresoftware/manticoresearch-python-asyncio) ✱ |
| PHP | Официальный клиент | [Официальный PHP-клиент](https://github.com/manticoresoftware/manticoresearch-php) |
| Java | Официальный клиент | [Официальный Java-клиент](https://github.com/manticoresoftware/manticoresearch-java) |
| Go | Официальный клиент ✱ | [Официальный Go-клиент](https://github.com/manticoresoftware/manticoresearch-go) |
| Rust | Клиент, поддерживаемый сообществом ✱ | [Официальный Rust-клиент](https://github.com/manticoresoftware/manticoresearch-rust) ✱ |
| Elixir † | Не указан в документации SDK Meilisearch | [Официальный Elixir-клиент](https://github.com/manticoresoftware/manticoresearch-elixir) |
| Dart/Flutter | Официальный клиент | Официального клиента нет (HTTP JSON API) |
| .NET/C# | Официальный клиент ✱ | [Официальный .NET-клиент](https://github.com/manticoresoftware/manticoresearch-net) |
| REST API | Основной интерфейс | Полный HTTP/JSON API |
| SQL | Не поддерживается | Нативный SQL (протокол MySQL) |

† — язык не был указан в исходной таблице; ✱ — статус уточнён по актуальной документации SDK Meilisearch

У Manticore Search есть официальные клиенты для девяти из десяти перечисленных языков; исключение — Dart/Flutter. У Meilisearch официальные клиенты есть для восьми языков: клиент Rust поддерживается сообществом, а Elixir в документации не указан. Оба движка предоставляют REST API, а Manticore Search дополнительно поддерживает SQL через протокол MySQL. Вывод статьи о широком выборе клиентов верен, но сведения о конкретных языках требовали обновления.

## Что в итоге

Meilisearch — хороший поисковый движок, особенно для мгновенного поиска прямо из пользовательского интерфейса. Однако если систему выбирают надолго, важно учитывать и ограничения, о которых говорится в сравнении Meilisearch. Например, движок обрабатывает только первые десять слов запроса, а остальные игнорирует. Такие особенности могут не мешать в начале, но со временем становятся существенными.

Статья описывает Manticore Search как сложную систему для крупных аналитических проектов, работающую только через SQL. В 2026 году это описание уже не соответствует возможностям движка. Базовый сценарий можно проверить за несколько минут в терминале:

```bash
curl https://manticoresearch.com | sh
```

После установки достаточно добавить JSON-документ и выполнить поиск ([подробнее об однострочном установщике](/blog/one-line-installer/)). Заранее описывать схему, готовить конфигурационный файл или заниматься «глубокой кастомизацией» не требуется. Численные результаты приведены выше; дополнительные данные доступны в нашем [сравнении на основе бенчмарков](/blog/manticoresearch-vs-meilisearch/) и на [db-benchmarks.com](https://db-benchmarks.com/). Если мы где-то неверно описали Meilisearch, поправим статью. Надеемся, что авторы сравнения так же исправят неточности в описании Manticore Search.

Обсудить сравнение можно на [форуме](https://forum.manticoresearch.com/) или в [Slack](https://slack.manticoresearch.com/).
