如何从Elasticsearch多索引中按规则获取总计20条文档?
解决方案
要实现"优先从每个索引取4条,总数凑够20条"的需求,不能直接用单一的match_all查询(它会随机从各索引分配条数,无法保证优先每个索引取4条),推荐以下两种实现方式:
方式一:使用Multi-Search API 分两次请求
第一步:批量获取每个索引的前4条文档
通过multi_search API一次性请求所有目标索引,每个索引单独指定size:4,这样能确保每个索引优先返回最多4条文档。
请求体示例:
{ "requests": [ {"index": "a", "body": {"query": {"match_all": {}}, "size":4, "sort": {"created_at": "desc"}}}, {"index": "b", "body": {"query": {"match_all": {}}, "size":4, "sort": {"created_at": "desc"}}}, {"index": "c", "body": {"query": {"match_all": {}}, "size":4, "sort": {"created_at": "desc"}}}, {"index": "d", "body": {"query": {"match_all": {}}, "size":4, "sort": {"created_at": "desc"}}}, {"index": "e", "body": {"query": {"match_all": {}}, "size":4, "sort": {"created_at": "desc"}}}, {"index": "f", "body": {"query": {"match_all": {}}, "size":4, "sort": {"created_at": "desc"}}} ] }
第二步:补充空缺条数
把第一步返回的所有文档合并后,统计总数:
- 如果总数已经达到20,直接返回结果;
- 如果总数不足20,计算缺口数量(比如缺
20 - 当前总数条),再执行一次跨所有索引的查询,排除已经获取到的文档ID,取对应缺口数量的最新文档。
补充查询的请求体示例(假设缺口是3条):
{ "index": ["a","b","c","d","e","f"], "body": { "query": { "bool": { "must": [{"match_all": {}}], "must_not": [{"ids": {"values": ["已获取的文档ID1", "已获取的文档ID2", ...]}}] } }, "size": 3, "sort": {"created_at": "desc"} } }
方式二:使用聚合+客户端处理
通过terms聚合按_index字段分组,每个分组用top_hits子聚合取前4条文档,之后在客户端合并结果,若总数不足20则补充查询。
请求体示例:
{ "index": ["a","b","c","d","e","f"], "body": { "size": 0, "aggs": { "per_index": { "terms": { "field": "_index", "size": 6 // 对应你的索引数量 }, "aggs": { "top_docs": { "top_hits": { "size": 4, "sort": {"created_at": "desc"} } } } } } } }
返回结果中,每个索引的top_docs.hits.hits就是该索引的前4条文档。把所有这些文档收集起来后,若总数不够20,再执行方式一中的补充查询即可。
为什么当前方案不满足需求
你当前的match_all+size:20查询,Elasticsearch会按照分片的查询结果合并逻辑返回文档,无法保证每个索引优先分配4条,可能出现某个索引返回远超4条,而其他索引返回很少的情况,不符合你的需求。
内容的提问来源于stack exchange,提问作者Ajay Makwana
相关产品推荐
相关产品推荐

