# Meilisearch 对比 Manticore：把事实说清楚

Meilisearch 发布了一篇对比 Meilisearch 和 Manticore Search 的文章。我们用两个引擎的最新版本核查了这些说法，以下是重新审视后的结果，附带可复现的命令。

几天前，Meilisearch 发布了[一篇对比 Meilisearch 和 Manticore Search 的文章](https://www.meilisearch.com/blog/meilisearch-vs-manticore)。我们喜欢对比，早在 2023 年我们就[发布过自己的对比](/blog/manticoresearch-vs-meilisearch/)，而且附带了你可以复现的基准测试。公平地说，Meilisearch 那篇对比的部分内容是准确的，甚至对 Manticore 还算宽厚。

但关于 Manticore 的几项说法已经过时，或者根本不是你在当前版本里运行时会观察到的情况。所以我们没有争论，而是照常做了我们一直会做的事：启动两个引擎的最新版本（Manticore Search 28.4.4 和 Meilisearch 1.41/1.48）并测试这些说法。下面的每条命令和返回结果都是真实的，欢迎直接复制粘贴验证我们。

## “全文搜索和实时分析”——这可能只占了 1%

文章这样介绍 Manticore：

> Manticore Search is an open-source search engine built as a continuation of Sphinx, improving its functionality with full-text search and real-time analytics.

Sphinx *本来就是* 全文搜索，而实时分析只是后来新增内容中的一小部分。下面是这些年“改进其功能”到底体现在哪里：

- **[RT 模式](/blog/rt_vs_plain_mode/)**——Sphinx 就有 RT 索引，但现在整个引擎无需配置文件即可运行：`CREATE TABLE`、插入、即时搜索
- **[复制](/blog/mike-replication/)**——基于 Galera 的同步集群复制
- **完整的 HTTP JSON API**——几乎 SQL 能做的都能做，还支持与 Elasticsearch 兼容的 bulk 端点
- **[自动建模](/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/) 支持，以及面向 AI 助手的 [MCP 服务器](/blog/mcp-manticore-server/)

“Sphinx 加实时分析”远远低估了它。

## “配置复杂”和“高级定制”吗？我们来数命令

文章对 Manticore 的结论：

> 最适合：需要高级定制、熟悉 SQL、并且要在大规模场景下进行高性能查询的大型项目和团队。

而缺点之一是：“配置复杂：初始配置和调优可能很耗时。”

下面是 Manticore 从零到可搜索的全部“复杂配置”：只要三个命令，没有配置文件，没有 schema：

**1. 安装（并启动 - [一行安装器](/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 自动推断出的 schema：

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

现在看 Meilisearch 做同样的事（我们测试了 `latest` Docker 标签、v1.41.0，以及最新发布版 v1.48.3）。Meilisearch 的安装器会把二进制下载到当前目录，然后你需要自己运行它，而且在生产模式下启动前还要先配置 master key。添加文档和搜索和 Manticore 一样简单，这点该给它肯定。但接着你再尝试过滤：

```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 中，[分面搜索完全不需要手动构建过滤条件](/blog/faceted-search-without-manual-filter-building/)。
- **排序也不行。** [根据 Meilisearch 的文档](https://www.meilisearch.com/docs/learn/filtering_and_sorting/sort_search_results)：*“要让用户在搜索时对结果排序，你必须……把这些属性加入 `sortableAttributes` 索引设置。”*
- **调整搜索字段也会触发重新索引。** `searchableAttributes` 的顺序决定相关性，因此限制或重新排序是大多数真实项目都会做的一步，而 *“更新 `searchableAttributes` 会触发索引中所有文档的重新索引。”*

这都不是 bug，而是设计取舍，而且每一步都只是一个小小的 API 调用。但它会累积成一种模型：你要按属性逐个声明能力，并且每次改变主意都要为整个数据集支付一次全量重新索引的代价。Manticore 的模型不同：字段有*类型*——文本字段可全文搜索，属性（数字、字符串、JSON）可过滤、排序、分组和分面，向量可进行 KNN 搜索——而且某种类型的所有能力在插入时就已经可用。这里没有需要维护的逐属性能力注册表，也不需要通过重新索引来改变查询方式。深度定制——排序公式、分词、形态学、字段权重——当然也有（文章的优点列表在这一点上是对的），但它是可选项，不是前提。所以我们不确定“需要高级定制”指向的是不是正确的引擎。

## “熟悉 SQL”——可选，不是必需

文章把 Manticore 描述成“适合熟悉 SQL 的团队”的选择。SQL 支持*确实*是 Manticore 的一个显著优势——你可以用任何 MySQL 客户端、`mysqldump`，或者 BI 工具来连接它（对比文章自己的集成表把这一点在 Meilisearch 中标成了“Not supported”）。

但注意你刚才在上面看到的内容：整个快速开始演示用的是通过 HTTP 传输的 JSON。实际上，Manticore 几乎所有功能都能通过两种方式使用——喜欢的话可以用 SQL，不喜欢的话可以用一个和 Meilisearch、Elasticsearch 用户非常熟悉的 JSON API。你完全不需要写一行 SQL 就能使用 Manticore。

## 向量搜索：Meilisearch 自己的表格已经说明了一切

这是我们最喜欢的部分。Meilisearch 文章里的用例表对两个引擎的向量搜索评价如下：

> **向量搜索。** Meilisearch：基础向量搜索。Manticore Search：更适合混合和高级场景。

我们同意这两列的结论。下面看看在 [自动嵌入](/blog/auto-embeddings/) 下，“混合和高级场景”在实践中是什么样子——不需要外部 embedding 流水线，不需要 API key，模型会自动下载：

```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 插入——嵌入向量会自动为你生成（也有一个用于批量处理的 `/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 上：[带过滤、分面、容错拼写和语义搜索的目录搜索](https://catalog.manticoresearch.com/)；[反向图片搜索](https://image.manticoresearch.com/)；以及[对话式搜索](https://chat.manticoresearch.com/)。

## 相关性：靠测量，不靠争论

搜索质量的说法可以通过实证来检验。我们在 14 组公开 IR 数据集/语料规模上，对 Manticore Search 和 Meilisearch 的全文、向量和混合模式做了基准测试：7 个 BEIR 数据集、ACORD、分别包含 250K 和 8.8M 文档的 MS MARCO Passage、TREC DL 2019/2020、Wayfair 的 WANDS 商品搜索数据集，以及专注拼写错误的 DL-Typo。对于每个引擎/模式组合，我们取每组中表现最好的完整运行结果，并在各组之间计算未加权平均。第一行则是在平均之前先为每组选出各引擎的最佳模式。向量和混合运行在两个引擎上都使用同一个 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 在 14 组里有 11 组领先。向量质量几乎持平，分别是 0.530 和 0.527；两个引擎使用同一个嵌入模型，但索引和检索实现仍然不同。混合结果差距更大，Manticore 的 RRF 平均值为 0.515，对比 0.475。

全文搜索的差距最大：0.420 对 0.237。更广泛的基准测试可以解释这一点。使用 BM25 或 BM25 家族排序器的引擎在全文相关性上普遍明显优于 Meilisearch。[Meilisearch 采用的是一组按顺序执行的规则](https://www.meilisearch.com/docs/learn/relevancy/ranking_rules)，依据词匹配、拼写错误、距离、属性和精确度来排序。因此它缺少 BM25 的逆文档频率、词频饱和和文档长度归一化的组合，这也是它在这些标准 IR 数据集上表现较差的主要原因。Typesense 也是更大范围对比中的另一款不使用 BM25 的引擎，表现模式也类似。Meilisearch 的十词查询限制在更长查询中还会进一步拖累结果，因为多出来的词会被忽略。

Manticore 在专注于拼写容错的 DL-Typo 上也领先。

同一套框架还测试了 Elasticsearch、OpenSearch、Qdrant、Typesense、Vespa 和 Weaviate。由于基准服务器可用资源有限，一些引擎没能完成最大规模的测试，所以报告提供了两个按覆盖率控制的排行榜。按所有 8 个引擎都覆盖到的 10 组子集重新计算后，Manticore 的最佳模式平均值排在第二，总体落后于 Qdrant。按全部 14 组计算，在完成全部覆盖的 5 个引擎中它也排第二。Meilisearch 在这两种比较中都记录了更低的平均值。

[完整对比](https://gist.github.com/manticoresearch/7c9b5d85ca8a62ce0066db6f0e17a11a) 已经包含覆盖率、按数据集拆分的表格，以及每次运行的精确配置。不过这项工作仍在进行中。我们很快会发布完整的方法论和其余细节。我们也会把新的基准测试工具开源，让这类基准测试更容易运行和扩展。

## “主要用于复杂的大规模工作负载”——数据并非如此

文章声称：

> Manticore 主要用于需要高性能和深度定制的复杂、大规模搜索和分析工作负载。

而在用例表中，Manticore “对于简单 CMS 需求可能有些过度”。

我们查看了[匿名遥测](https://manual.manticoresearch.com/Telemetry)。在报告数据大小指标的 Manticore 实例中：

- **29%** 的数据量小于 **1 MB**
- 大约 **一半** 的数据量小于 **100 MB**
- 只有大约 **八分之一** 超过 **10 GB**，而少于 **1%** 超过 **1 TB**

所以，不，Manticore *并不*主要用于大规模工作负载。现实中的大多数 Manticore 部署都是小型项目：网站、目录、博客、内部工具。正好就是表格里提醒你要注意的那类“简单 CMS 需求”。一个 Manticore 容器待机时内存占用不到 200 MB，而且正如你上面看到的，做出一个可用搜索只要三个命令——很难说这对任何场景都是过度配置。

好的一面是，同一个引擎在另一端同样撑得住：从 Elasticsearch 迁移后，[在 Manticore 上本地每秒可处理数万次查询](/blog/manticore-search-at-scale-on-google-cloud/)。向下扩展和向上扩展并不互斥。

## 实时分析：这一点我们也直说

有意思的是，同一张表给了 Manticore 一个我们自己都愿意稍微保守点说的评价：“专为实时数据和分析而设计。”Manticore 确实具备很强的分析能力——[列式存储](/blog/mcl/)、聚合、[Kibana](/blog/kibana-demo/) 和 [Grafana](/blog/grafana-dashboard-docker/) 集成、[日志管道集成](/blog/integration-of-manticore-with-logstash-filebeat/)——而且它[非常适合日志搜索](/blog/kibana-demo/)。但它首先是一款搜索引擎。分析只是它的一个用例，而不是它“主要设计用途”，也不是大多数用户实际使用它的原因。

## Meilisearch 文章说得有道理的地方

我们承诺要讲事实，而事实是双向的：

- **默认就有拼写容错。** 这是真的：Meilisearch 默认开启了拼写容错。在 Manticore 中，[模糊搜索](/blog/new-fuzzy-search-and-autocomplete/) 是可选开启的——在表定义中设置 `min_infix_len='2'`，并在查询时设置 `fuzzy=1`。这两个设置都很小，但 Meilisearch 的默认体验更友好。
- **直接从前端查询。** Meilisearch 的 search API key 让无需后端的搜索成为一级模式。Manticore 传统上是放在后端后面使用的；[认证在 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 列了两次，而且给出了相互矛盾的答案（“supported via community”和“not supported”），还把多个官方/社区状态写错了——两边都有，方向也都有问题——并且漏掉了两个语言。下面这版是根据[Meilisearch 自己的 SDK 文档](https://www.meilisearch.com/docs/learn/resources/sdks)和[Manticore 的 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 | 官方客户端（同步 + 异步） | 官方 [sync](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 † | Meilisearch 的 SDK 文档中未列出 | [官方 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 协议） |

† — 原表中缺失的语言 • ✱ — 相较原表已纠正状态（对于 Meilisearch 一列，以其当前 SDK 文档为准）

把上面十种语言合在一起看：**Manticore 提供 9 种官方客户端**——只有 Dart/Flutter 例外。**Meilisearch 提供 8 种官方客户端**——只有 Rust（社区维护）和 Elixir（未列出）例外。两者都完整支持 REST，而 Manticore 还额外通过 MySQL 协议支持 SQL。所以“广泛的客户端范围”——原文对 Manticore 集成的这句评价——是准确的；只是细节需要更新了。

## 结论

Meilisearch 是一款不错的搜索引擎，而这篇文章有一点说得没错：它在即时搜索、以前端为中心的使用场景上打磨得很好。不过如果你是在做长期选择，也要把 Meilisearch 自己文章里列出的缺点一并考虑进去——比如一个搜索查询“必须不超过十个词，更多的会被忽略”。这类限制在第六个月往往比第一天更重要。

但更大的问题在于，文章里描述的那个 Manticore——一个面向大规模分析团队的、复杂的、只能靠 SQL 的系统——并不是 2026 年真实存在的 Manticore，而且其中大部分你在大约五分钟的终端时间里就能证伪：

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

然后插入一个 JSON 文档并搜索它（关于一行安装器的更多内容见[这里](/blog/one-line-installer/)）。没有 schema，没有配置，没有“高级定制”。如果你更想看数字而不是文字，上面的相关性结果、我们的[基于基准测试的对比](/blog/manticoresearch-vs-meilisearch/)以及 [db-benchmarks.com](https://db-benchmarks.com/) 都是不错的起点；如果我们这里对 Meilisearch 有任何说错的地方，我们也很乐意更正。我们也希望别人这样对待我们。

有问题或不同意见？欢迎到[论坛](https://forum.manticoresearch.com/)或 [Slack](https://slack.manticoresearch.com/) 里告诉我们。
