Elasticsearch:如何设置SearchHit?如何获取超过10条SearchHit结果?
嘿,我来帮你搞定Elasticsearch里的这两个问题——关于SearchHit的设置,还有怎么拿到超过默认10条的查询结果:
一、关于SearchHit的设置
首先得明确:SearchHit是Elasticsearch查询后返回的结果实体,我们没法直接手动“设置”它本身,但可以通过调整查询请求的参数,来控制返回的SearchHit包含哪些内容、格式是什么样的。常见的自定义方式有这些:
- 指定返回字段:用
fetchSource()方法过滤字段,只返回你需要的数据,减少传输开销。比如Java客户端的写法:
SearchRequest searchRequest = new SearchRequest("your_index"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // 只返回title和content字段,第二个参数是排除的字段(这里为空) sourceBuilder.fetchSource(new String[]{"title", "content"}, new String[]{}); searchRequest.source(sourceBuilder);
- 添加高亮效果:如果需要高亮显示匹配的关键词,设置高亮参数后,返回的SearchHit里会包含高亮片段:
HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.field("content"); // 指定要高亮的字段 highlightBuilder.preTags("<em>"); // 高亮前缀 highlightBuilder.postTags("</em>"); // 高亮后缀 sourceBuilder.highlighter(highlightBuilder); // 后续从SearchHit中获取高亮内容: // hit.getHighlightFields().get("content").getFragments()
- 添加脚本字段:如果需要在结果中动态计算字段(比如折扣价),可以用脚本字段,这些字段会出现在SearchHit的
getFields()中:
// 用painless脚本计算原价打9折后的价格 Script discountScript = new Script(ScriptType.INLINE, "painless", "doc['original_price'].value * 0.9", Collections.emptyMap()); sourceBuilder.scriptField("discounted_price", discountScript);
- 控制排序规则:自定义SearchHit的返回顺序,比如按评分、时间排序:
// 先按相关性评分降序,再按创建时间降序 sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); sourceBuilder.sort(new FieldSortBuilder("create_time").order(SortOrder.DESC));
二、如何获取超过默认10条的SearchHit结果
Elasticsearch默认只返回10条结果,这是出于性能优化的考虑。要获取更多结果,分三种场景选择合适的方案:
1. 小数据量场景:用from和size参数
这是最简单的方式,直接设置起始位置和返回数量。比如要获取第11到30条结果:
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // from是起始索引(从0开始),size是返回条数 sourceBuilder.from(10); sourceBuilder.size(20);
⚠️ 注意:ES默认限制size最大为10000(可以修改index.max_result_window参数调整),但如果数据量超过1万条,这种方式会有性能瓶颈——因为ES需要在内存中对所有匹配结果排序,再截取部分返回,数据量越大越耗资源。
2. 大数据量场景:用Scroll API
如果需要导出几十万甚至上百万条数据,推荐用Scroll API,它会创建一个查询结果的快照,然后分批获取:
// 第一步:初始化Scroll,设置快照过期时间(比如1分钟) SearchRequest searchRequest = new SearchRequest("your_index"); SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.size(100); // 每次获取100条 searchRequest.source(sourceBuilder); searchRequest.scroll(TimeValue.timeValueMinutes(1)); SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); String scrollId = searchResponse.getScrollId(); SearchHit[] hits = searchResponse.getHits().getHits(); // 第二步:循环获取所有批次的结果 while (hits != null && hits.length > 0) { // 处理当前批次的SearchHit for (SearchHit hit : hits) { // 你的业务逻辑,比如解析数据、存储等 } // 发送下一批次的Scroll请求 SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); scrollRequest.scroll(TimeValue.timeValueMinutes(1)); searchResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT); scrollId = searchResponse.getScrollId(); hits = searchResponse.getHits().getHits(); } // 第三步:清理Scroll快照,避免占用ES资源 ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); clearScrollRequest.addScrollId(scrollId); client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
3. 实时数据场景:用Search After
如果你的数据是实时更新的,Scroll API的快照可能会包含旧数据,这时候用Search After更合适——它基于上一批结果最后一条的排序值来获取下一批,保证拿到最新数据:
// 第一步:第一次查询,必须设置唯一的排序规则(比如id+时间,避免重复或遗漏) SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.size(100); // 先按相关性评分降序,再按唯一id降序(保证排序唯一) sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.DESC)); SearchResponse searchResponse = client.search(new SearchRequest("your_index").source(sourceBuilder), RequestOptions.DEFAULT); SearchHit[] hits = searchResponse.getHits().getHits(); // 第二步:循环获取下一批结果 while (hits != null && hits.length > 0) { // 处理当前批次数据 for (SearchHit hit : hits) { // 你的业务逻辑 } // 获取上一批最后一条的排序值 Object[] lastSortValues = hits[hits.length - 1].getSortValues(); // 设置Search After参数,基于最后一条的排序值获取下一批 sourceBuilder.searchAfter(lastSortValues); searchResponse = client.search(new SearchRequest("your_index").source(sourceBuilder), RequestOptions.DEFAULT); hits = searchResponse.getHits().getHits(); }
内容的提问来源于stack exchange,提问作者Nikita Krasnov
相关产品推荐
相关产品推荐

