Manticore Search 29.9.0 查询语言与 API 使用详解
Manticore Search 29.9.0 查询语言与 API 使用详解:SphinxQL(MySQL 协议)+ HTTP JSON 全实测,覆盖建表、写入、全文检索、过滤排序分组、分面、高亮、更新删除、批量操作的完整语法与真实响应回显。
Manticore Search 29.9.0 查询语言与 API 使用详解
目标:系统掌握 Manticore Search 29.9.0 的两种查询接口——SphinxQL(MySQL 协议,9306 端口)与 HTTP JSON API(9308 端口),覆盖建表、写入、全文检索、过滤排序分组、分面、高亮、批量操作的完整语法与实测响应。文中所有语句与请求均为实测,取材日期 2026-10-25,环境 Ubuntu 24.04 + Manticore Search 29.9.0。部署见《Manticore Search 29.9.0 Docker Compose 部署指南》,配置见《Manticore Search 29.9.0 配置参数详解》。
一、环境信息
- 应用版本:Manticore Search
29.9.0,columnar 14.2.1,buddy v4.4.3 - 接口端口:9306(SphinxQL / MySQL 协议)、9308(HTTP JSON)
- 客户端工具:
curl(HTTP)、mysql客户端(SphinxQL) - 测试表:
products(id bigint、title text indexed stored、price float、category uint),预置 7 条文档 - 认证:默认无认证,生产环境需配合反向代理或网络隔离
二、API 总览
Manticore Search 提供两种等价的查询接口,功能重叠但使用场景不同:
| 接口 | 端口 | 协议 | 适用场景 | 返回格式 |
|---|---|---|---|---|
| SphinxQL | 9306 | MySQL 协议 | 习惯 SQL、用 MySQL 客户端/BI 工具连接 | 表格 |
| HTTP JSON | 9308 | HTTP | 应用程序集成、脚本自动化 | JSON |
HTTP JSON 接口下又分多个端点:
| 端点 | 方法 | 用途 |
|---|---|---|
/cli | POST | 执行任意 SQL(DDL/DML/SELECT),返回文本表格 |
/sql | POST | 仅执行 SELECT,返回 JSON |
/search | POST | JSON 格式搜索请求 |
/insert | POST | JSON 格式插入单条 |
/delete | POST | JSON 格式删除 |
/update | POST | JSON 格式更新属性 |
/replace | POST | JSON 格式替换(存在则更新,不存在则插入) |
/bulk | POST | NDJSON 批量操作 |
💡 技术拓展:SphinxQL 与 HTTP JSON 的分工。
接口 优势 劣势 SphinxQL SQL 语法熟悉、兼容 MySQL 生态 需 MySQL 客户端、部分操作(高亮)需 CALL 函数 HTTP JSON 无客户端依赖、原生高亮/分面、易集成 语法与 SQL 不同、需熟悉 JSON DSL 本文以 HTTP JSON 为主线展开,SphinxQL 给出等价写法。两者底层查询引擎相同,性能一致。
三、建表与表结构
3.1 建表(HTTP /cli)
curl -s "http://127.0.0.1:9308/cli" -d 'CREATE TABLE products (title text, price float, category int)'
实测回显:
Query OK, 0 rows affected (0.002 sec)
3.2 查看表列表
curl -s "http://127.0.0.1:9308/cli" -d 'SHOW TABLES'
实测回显:
+----------+------+
| Table | Type |
+----------+------+
| products | rt |
+----------+------+
1 row in set (0.003 sec)
rt 表示实时表(Real-Time),支持实时写入。
3.3 查看表结构
curl -s "http://127.0.0.1:9308/cli" -d 'DESCRIBE products'
实测回显:
+----------+--------+----------------+
| Field | Type | Properties |
+----------+--------+----------------+
| id | bigint | |
| title | text | indexed stored |
| price | float | |
| category | uint | |
+----------+--------+----------------+
title 是 text indexed stored:既参与全文索引,又可返回原值。price 与 category 是属性,用于过滤/排序/分组。
3.4 SphinxQL 等价写法
用 MySQL 客户端连接 9306 端口:
mysql -h 127.0.0.1 -P 9306 -e "SHOW TABLES; DESCRIBE products;"
实测回显:
+----------+------+
| Table | Type |
+----------+------+
| products | rt |
+----------+------+
+----------+--------+----------------+
| Field | Type | Properties |
+----------+--------+----------------+
| id | bigint | |
| title | text | indexed stored |
| price | float | |
| category | uint | |
+----------+--------+----------------+
四、写入数据
4.1 单条插入(HTTP /cli)
curl -s "http://127.0.0.1:9308/cli" -d "INSERT INTO products (id, title, price, category) VALUES (1, 'Manticore Search full text engine', 99.50, 1)"
实测回显:
Query OK, 1 row affected (0.003 sec)
4.2 JSON 格式插入(HTTP /insert)
curl -s -X POST "http://127.0.0.1:9308/insert" -H 'Content-Type: application/json' -d '{"index":"products","id":6,"doc":{"title":"OpenSearch fork of elasticsearch","price":150.0,"category":1}}'
实测回显:
{"table":"products","id":6,"created":true,"result":"created","status":201}
4.3 批量插入(HTTP /bulk)
/bulk 接受 NDJSON(每行一个 JSON 对象),批量写入性能远高于逐条插入:
curl -s -X POST "http://127.0.0.1:9308/bulk" -H 'Content-Type: application/x-ndjson' -d '{"insert":{"index":"products","id":7,"doc":{"title":"Sphinx legacy fulltext","price":0.0,"category":2}}}
{"insert":{"index":"products","id":8,"doc":{"title":"Lucene based search","price":30.0,"category":1}}}
'
实测回显:
{"items":[{"bulk":{"table":"products","_id":8,"created":2,"deleted":0,"updated":0,"result":"created","status":201}}],"current_line":3,"skipped_lines":0,"errors":false,"error":""}
created: 2 表示成功写入 2 条,errors: false 表示无错误。
4.4 SphinxQL 等价写法
INSERT INTO products (id, title, price, category) VALUES
(1, 'Manticore Search full text engine', 99.50, 1),
(2, 'Elasticsearch distributed search engine', 199.00, 1),
(3, 'Typesense typo tolerant search', 49.00, 1),
(4, 'Meilisearch instant search engine', 0, 1),
(5, 'Sphinx full text search server', 0, 2);
五、全文检索
全文检索是搜索引擎的核心能力,通过 MATCH('查询语法') 函数实现。
5.1 基础全文检索(HTTP /sql)
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, title, price FROM products WHERE MATCH('search')"
实测回显:
{"took":0,"timed_out":false,"hits":{"total":5,"total_relation":"eq","hits":[
{"_id":2,"_score":1295,"_source":{"title":"Elasticsearch distributed search engine","price":199.000000}},
{"_id":3,"_score":1295,"_source":{"title":"Typesense typo tolerant search","price":49.000000}},
{"_id":4,"_score":1295,"_source":{"title":"Meilisearch instant search engine","price":0.000000}},
{"_id":5,"_score":1295,"_source":{"title":"Sphinx full text search server","price":0.000000}},
{"_id":1,"_score":1295,"_source":{"title":"Manticore Search full text engine","price":99.500000}}
]}}
_score 是 BM25 相关度分数,took 是查询耗时(毫秒)。
⚠️
MATCH()的参数必须用单引号包裹,不能用双引号。/sql端点的query参数需要 URL 编码,建议用--data-urlencode。
5.2 多词查询与操作符
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, title, WEIGHT() FROM products WHERE MATCH('search engine') ORDER BY WEIGHT() DESC"
实测回显:
{"took":0,"timed_out":false,"hits":{"total":3,"total_relation":"eq","hits":[
{"_id":2,"_score":2397,"_source":{"title":"Elasticsearch distributed search engine","weight()":2397}},
{"_id":4,"_score":2397,"_source":{"title":"Meilisearch instant search engine","weight()":2397}},
{"_id":1,"_score":1397,"_source":{"title":"Manticore Search full text engine","weight()":1397}}
]}}
search engine 默认是 AND 关系(两个词都命中才返回)。WEIGHT() 返回该行的相关度分数。
5.3 字段限定搜索
用 @字段名 关键词 限定在某个全文字段中搜索:
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, title FROM products WHERE MATCH('@title engine')"
5.4 布尔操作符
| 操作符 | 含义 | 示例 |
|---|---|---|
| 空格 | AND(默认) | search engine |
| | OR | search | find |
- | NOT | search -engine |
"..." | 短语 | "search engine" |
@field | 字段限定 | @title search |
5.5 HTTP JSON 搜索(/search 端点)
curl -s -X POST "http://127.0.0.1:9308/search" -H 'Content-Type: application/json' -d '{"index":"products","query":{"match":{"title":"search engine"}},"limit":2}'
实测回显:
{"took":0,"timed_out":false,"hits":{"total":5,"total_relation":"eq","hits":[
{"_id":4,"_score":2397,"_source":{"title":"Meilisearch instant search engine","price":0.000000,"category":1}},
{"_id":2,"_score":2397,"_source":{"title":"Elasticsearch distributed search engine","price":199.000000,"category":1}}
]}}
JSON DSL 中 match 表示全文匹配,{"*":"keyword"} 表示在所有全文字段中搜索。
六、过滤、排序与分组
6.1 属性过滤
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, title FROM products WHERE category=1"
实测回显:
{"took":0,"timed_out":false,"hits":{"total":4,"total_relation":"eq","hits":[
{"_id":2,"_score":1,"_source":{"title":"Elasticsearch distributed search engine"}},
{"_id":3,"_score":1,"_source":{"title":"Typesense typo tolerant search"}},
{"_id":4,"_score":1,"_source":{"title":"Meilisearch instant search engine"}},
{"_id":1,"_score":1,"_source":{"title":"Manticore Search full text engine"}}
]}}
全文检索与属性过滤可组合:
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, title FROM products WHERE MATCH('search') AND category=1"
6.2 排序
按属性排序:
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, title, price FROM products ORDER BY price DESC LIMIT 3"
实测回显:
{"took":0,"timed_out":false,"hits":{"total":5,"total_relation":"eq","hits":[
{"_id":2,"_score":1,"_source":{"title":"Elasticsearch distributed search engine","price":199.000000}},
{"_id":1,"_score":1,"_source":{"title":"Manticore Search full text engine","price":99.500000}},
{"_id":3,"_score":1,"_source":{"title":"Typesense typo tolerant search","price":49.000000}}
]}}
按相关度排序:
... ORDER BY WEIGHT() DESC
6.3 分组聚合
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT category, COUNT(*) FROM products GROUP BY category"
实测回显:
{"took":0,"timed_out":false,"hits":{"total":2,"total_relation":"eq","hits":[
{"_score":1,"_source":{"category":2,"count(*)":1}},
{"_score":1,"_source":{"category":1,"count(*)":4}}
]}}
支持的聚合函数:COUNT(*)、SUM(attr)、AVG(attr)、MIN(attr)、MAX(attr)。
七、分面(Facet)
分面搜索是电商搜索的核心能力,返回每个属性值的文档计数。通过 HTTP /search 的 aggs 字段实现:
curl -s -X POST "http://127.0.0.1:9308/search" -H 'Content-Type: application/json' -d '{
"index":"products",
"query":{"match":{"*":"search"}},
"limit":0,
"aggs":{"by_category":{"terms":{"field":"category","size":10}}}
}'
实测回显:
{"took":0,"timed_out":false,"hits":{"total":2,"total_relation":"eq","hits":[]},"aggregations":{"by_category":{"buckets":[
{"key":2,"doc_count":1},
{"key":1,"doc_count":4}
]}}}
limit: 0 表示不返回命中文档,只返回分面结果。buckets 中每个 key 是属性值,doc_count 是该值的文档数。
八、高亮(Highlight)
搜索结果中把匹配的关键词用标记包裹,便于前端展示。通过 HTTP /search 的 highlight 字段实现:
curl -s -X POST "http://127.0.0.1:9308/search" -H 'Content-Type: application/json' -d '{
"index":"products",
"query":{"match":{"title":"search engine"}},
"highlight":{"fields":["title"],"pre_tags":["<b>"],"post_tags":["</b>"]},
"limit":2
}'
实测回显:
{"took":0,"timed_out":false,"hits":{"total":5,"total_relation":"eq","hits":[
{"_id":4,"_score":2397,"_source":{"title":"Meilisearch instant search engine","price":0.000000,"category":1},"highlight":{"title":["Meilisearch instant <b>search engine</b>"]}},
{"_id":2,"_score":2397,"_source":{"title":"Elasticsearch distributed search engine","price":199.000000,"category":1},"highlight":{"title":["Elasticsearch distributed <b>search engine</b>"]}}
]}}
highlight 字段返回带 <b> 标记的高亮文本,与 _source.title(原文)分开。
九、更新与删除
9.1 更新属性(HTTP /update)
curl -s -X POST "http://127.0.0.1:9308/update" -H 'Content-Type: application/json' -d '{"index":"products","id":1,"doc":{"price":120.0}}'
实测回显:
{"table":"products","id":1,"result":"updated"}
验证更新结果:
curl -s "http://127.0.0.1:9308/sql" --data-urlencode "query=SELECT id, price FROM products WHERE id=1"
实测回显:
{"took":0,"timed_out":false,"hits":{"total":1,"total_relation":"eq","hits":[{"_id":1,"_score":1,"_source":{"price":120.000000}}]}}
⚠️
/update只能更新属性(int/float/string 等),不能更新全文字段。更新全文字段需用/replace(整体替换文档)。
9.2 删除文档(HTTP /delete)
curl -s -X POST "http://127.0.0.1:9308/delete" -H 'Content-Type: application/json' -d '{"index":"products","id":6}'
实测回显:
{"table":"products","id":6,"found":true,"result":"deleted"}
found: true 表示文档存在并已删除。
十、查询性能与状态
10.1 查看服务状态
curl -s "http://127.0.0.1:9308/cli" -d "SHOW STATUS LIKE 'uptime'"
实测回显:
+---------+-------+
| Counter | Value |
+---------+-------+
| uptime | 82 |
+---------+-------+
10.2 查询性能统计
curl -s "http://127.0.0.1:9308/cli" -d "SHOW STATUS LIKE 'search_stats_ms%'"
返回 search_stats_ms_avg/min/max/pct95/pct99 等查询耗时百分位,用于性能监控。
10.3 查询日志
每条查询记录在 query.log 中,含连接来源、耗时、匹配数:
/* Sun Oct 25 12:07:56.465 2026 conn 576 (10.89.60.1:40348) real 0.000 wall 0.000 found 6 */ SELECT id FROM products WHERE MATCH('search');
real 是实际执行时间,wall 是墙钟时间,found 是匹配文档数。
十一、常见问题
Q1:/sql 端点执行 CREATE TABLE 报 only SELECT queries are supported
原因:/sql 只接受 SELECT。DDL/DML 用 /cli 端点。
Q2:MATCH("search") 报 syntax error, unexpected $undefined
原因:MATCH 参数必须用单引号,双引号会被解析为字段名。改为 MATCH('search')。
Q3:/bulk 返回 errors: true
原因:NDJSON 格式错误,每行必须是独立 JSON 对象,且行尾用 \n 分隔。检查每行 JSON 是否合法、字段名是否拼写正确。
Q4:更新全文字段不生效
原因:/update 只能更新属性。更新全文内容用 /replace 整体替换文档,或用 SphinxQL 的 REPLACE INTO。
Q5:查询返回结果数被限制为 1000
原因:max_matches 默认 1000。在查询中加 OPTION max_matches=5000 或会话级 SET max_matches=5000。
十二、参考链接
- Manticore Search 官方 HTTP JSON API 文档:https://manual.manticoresearch.com/Connecting_to_the_server/HTTP (查询日期 2026-10-25)
- Manticore Search 官方 SphinxQL 文档:https://manual.manticoresearch.com/Searching/Full_text_matching (查询日期 2026-10-25)
- Manticore Search 官方高亮文档:https://manual.manticoresearch.com/Searching/Highlighting (查询日期 2026-10-25)
- Manticore Search 官方分面文档:https://manual.manticoresearch.com/Searching/Faceting (查询日期 2026-10-25)