📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

在单个 HTTP 请求中执行多个搜索查询,减少网络往返时间。

API #

GET /_msearch
POST /_msearch
GET /{index}/_msearch
POST /{index}/_msearch

API 的作用 #

Multi Search API 允许在单个请求中执行多个搜索查询,服务器按顺序返回所有结果。

多搜索的优势 #

优势描述
减少网络开销单次请求完成多个搜索
提高吞吐量批量执行比单独执行更快
原子性每个搜索独立执行

多搜索 vs 单个搜索 #

方式请求次数适用场景
单个搜索N 次少量不同搜索
多搜索1 次多个相似搜索

API 的参数 #

路由参数 #

参数类型是否必填描述
{index}字符串索引名称。支持:单个索引、逗号分隔的多个索引、通配符表达式

Query String 参数 #

全局参数 #

参数类型是否必填默认值描述
max_concurrent_searches整数0最大并发搜索请求数(0 表示无限制)
pre_filter_shard_size整数128预过滤分片大小
max_concurrent_shard_requests整数自动最大并发分片请求数
ccs_minimize_roundtrips布尔值true最小化跨集群搜索往返

索引相关 #

参数类型是否必填默认值描述
search_type字符串query_then_fetch搜索类型
request_cache布尔值-是否使用请求缓存
preference字符串-首选分片副本:_local_primary
routing字符串-路由值
allow_partial_search_results布尔值-是否允许部分结果
expand_wildcards枚举值open通配符展开方式
ignore_unavailable布尔值false是否忽略不可用索引
allow_no_indices布尔值false是否允许空索引
ignore_throttled布尔值false是否忽略限流索引

请求体参数 #

请求体使用 NDJSON(换行分隔的 JSON)格式:

{ 头部1 }
{ 搜索体1 }
{ 头部2 }
{ 搜索体2 }
...

头部格式 #

{
  "index": "index_name",
  "search_type": "query_then_fetch",
  "preference": "_local",
  "routing": "routing_value",
  "allow_partial_search_results": true
}

搜索体格式 #

{
  "query": { ... },
  "size": 10,
  "from": 0,
  "sort": [ ... ],
  "aggs": { ... }
}

示例 #

基本多搜索 #

POST /_msearch
{ "index": "users" }
{ "query": { "match": { "name": "john" } }, "size": 5 }
{ "index": "products" }
{ "query": { "term": { "category": "electronics" } }, "size": 10 }

响应示例:

{
  "responses": [
    {
      "took": 5,
      "timed_out": false,
      "_shards": { ... },
      "hits": {
        "total": { "value": 1, "relation": "eq" },
        "max_score": 0.2876821,
        "hits": [ ... ]
      }
    },
    {
      "took": 3,
      "timed_out": false,
      "_shards": { ... },
      "hits": {
        "total": { "value": 10, "relation": "eq" },
        "max_score": 0.876543,
        "hits": [ ... ]
      }
    }
  ]
}

空头部(使用默认索引) #

POST /my_index/_msearch
{}
{ "query": { "match_all": {} }, "size": 10 }
{}
{ "query": { "term": { "status": "active" } }, "size": 5 }

每个搜索指定索引 #

POST /_msearch
{ "index": "logs" }
{ "query": { "match": { "level": "ERROR" } } }
{ "index": "metrics" }
{ "query": { "range": { "@timestamp": { "gte": "now-1h" } } } }

使用聚合 #

POST /sales/_msearch
{}
{ "size": 0, "aggs": { "by_category": { "terms": { "field": "category.keyword" } } } }
{}
{ "size": 0, "aggs": { "by_day": { "date_histogram": { "field": "@timestamp", "calendar_interval": "day" } } } }

使用搜索类型 #

POST /_msearch?search_type=dfs_query_then_fetch
{ "index": "products" }
{ "query": { "match": { "name": "laptop" } } }

使用路由 #

POST /_msearch
{ "index": "logs", "routing": "shard1" }
{ "query": { "term": { "server": "server1" } } }

条件过滤 #

POST /products/_msearch
{ "index": "products" }
{ "query": { "bool": { "filter": { "term": { "in_stock": true } } } } }
{ "index": "products" }
{ "post_filter": { "term": { "discounted": false } } }

设置超时 #

POST /_msearch?timeout=5s
{ "index": "my_index" }
{ "query": { "match_all": {} }, "timeout": "2s" }

不同排序 #

POST /_msearch
{ "index": "logs" }
{ "sort": [ { "@timestamp": "desc" } ], "query": { "match_all": {} } }
{ "index": "products" }
{ "sort": [ { "price": "asc" } ], "query": { "match_all": {} } }

获取特定字段 #

POST /_msearch
{ "_source": ["title", "author"] }
{ "index": "articles" }
{ "query": { "match": { "title": "search" } } }

请求格式说明 #

NDJSON 格式要求 #

  1. 成对结构:每个搜索由头部和体组成
  2. 换行分隔:每行之间用换行符 \n 分隔
  3. Content-Type:必须设置为 application/x-json
  4. 结尾换行:请求体末尾必须有换行符

格式示例 #

POST /_msearch
Content-Type: application/x-ndjson

{ "index": "users" }
{ "query": { "match": { "name": "john" } } }
{ "index": "products" }
{ "query": { "match": { "category": "electronics" } } }

响应字段说明 #

字段描述
responses每个搜索的响应数组
responses[].took执行时间(毫秒)
responses[].timed_out是否超时
responses._shards分片信息
responses[].hits搜索结果

使用场景 #

场景 1:仪表板多查询 #

POST /_msearch
{}
{ "size": 5, "query": { "match": { "level": "ERROR" } }, "sort": [ { "@timestamp": "desc" } ] }
{}
{ "size": 0, "query": { "bool": { "filter": { "range": { "@timestamp": { "gte": "now-1d" } } } }, "aggs": { "errors_per_hour": { "date_histogram": { "field": "@timestamp", "calendar_interval": "hour" } } } }
{}
{ "size": 1, "query": { "match": { "message": "critical" } } }

场景 2:多索引查询 #

POST /_msearch
{ "index": "logs-2024-*" }
{ "query": { "term": { "level": "ERROR" } } }
{ "index": "logs-2025-*" }
{ "query": { "term": { "level": "ERROR" } }

场景 3:不同分页 #

POST /products/_msearch
{}
{ "from": 0, "size": 10, "query": { "match": { "category": "electronics" } } }
{}
{ "from": 10, "size": 10, "query": { "match": { "category": "electronics" } } }
{}
{ "from": 20, "size": 10, "query": { "match": { "category": "electronics" } } }

场景 4:聚合查询 #

POST /analytics/_msearch
{}
{ "size": 0, "aggs": { "users": { "cardinality": { "field": "user_id.keyword" } } } }
{}
{ "size": 0, "aggs": { "categories": { "terms": { "field": "category.keyword" } } } }
{}
{ "size": 0, "aggs": { "dates": { "date_histogram": { "field": "date", "calendar_interval": "day" } } } }

搜索类型 #

类型描述
query_then_fetch默认,先查询再获取
dfs_query_then_fetch先分布式查询再获取(不推荐)
query_and_fetch查询并获取(已弃用)
dfs_query_and_fetch分布式查询并获取(已弃用)

注意事项 #

  1. 格式要求:必须使用 NDJSON 格式
  2. Content-Type:必须设置为 application/x-ndjson
  3. 错误处理:单个搜索失败不影响其他搜索
  4. 性能考虑:大量搜索可能占用较多资源
  5. 大小限制:每个搜索有独立的 from+size 限制