Elasticsearch中inner_hits超100条时如何实现滚动查询?
解决Inner Hits分页绕过max_inner_result_window限制的方案
Elasticsearch确实没有给inner_hits提供原生的Scroll分页能力,但可以通过以下几种方式绕过max_inner_result_window的配置限制,无需修改集群参数:
1. 反向查询+Scroll遍历嵌套文档
嵌套字段在ES内部是以独立Lucene文档的形式存储的,你可以反过来用has_parent查询直接定位这些嵌套文档,再通过Scroll API遍历所有匹配结果,同时关联回父文档信息:
// 初始化Scroll查询 POST /your_index/_search?scroll=1m { "query": { "has_parent": { "parent_type": "你的父文档类型", "query": { // 这里填写原本过滤父文档的条件 "match": {"parent_field": "过滤值"} } } }, "size": 100, "_source": ["nested_field.*", "_parent"] // 指定返回嵌套字段和父文档ID }
之后用Scroll API循环获取下一批结果,直到返回数据为空,最后清理Scroll上下文:
POST /_search/scroll { "scroll": "1m", "scroll_id": "上一次返回的scroll_id" }
2. 使用Point-in-Time (PIT) + Search After(推荐ES 7.10+)
PIT是Scroll的替代方案,更节省资源。先创建PIT,再通过Search After分页获取嵌套项:
- 第一步:创建PIT
POST /your_index/_pit?keep_alive=1m
- 第二步:首次查询
POST /_search { "size": 100, "query": { "has_parent": { "parent_type": "你的父文档类型", "query": { // 父文档过滤条件 } } }, "pit": { "id": "返回的PIT_ID", "keep_alive": "1m" }, "sort": ["_doc"] // 用_doc排序保证分页顺序稳定 }
- 后续分页:用上一次结果最后一条的
sort值作为search_after参数
POST /_search { "size": 100, "pit": { "id": "PIT_ID", "keep_alive": "1m" }, "search_after": ["上一次最后一条的sort值"], "sort": ["_doc"] }
- 完成后删除PIT
DELETE /_pit { "id": "PIT_ID" }
3. 按嵌套字段属性拆分查询
如果嵌套项有可拆分的维度(比如时间范围、分类标签),可以把大结果集拆分成多个小批次查询。比如按嵌套项的创建时间分天查询,确保每个批次的匹配结果不超过max_inner_result_window,最后合并所有批次的数据。
内容的提问来源于stack exchange,提问作者Mukul Sikarwar
相关产品推荐
相关产品推荐

