Search Scroll API
Scroll API可用于从搜索请求中检索大数量的结果。
为了使用滚动,需要按照给定的顺序执行以下步骤。
初始化搜索滚动上下文
包含一个 scroll 参数的初始化搜索请求必须通过执行 Search API 初始化滚动回话。 在处理此SearchRequest时,Elasticsearch将检测滚动参数的存在,并使搜索上下文保持相应的时间间隔。
SearchRequest searchRequest = new SearchRequest("posts");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(matchQuery("title", "Elasticsearch"));
searchSourceBuilder.size(size); //Create the SearchRequest and its corresponding SearchSourceBuilder. Also optionally set the size to control how many results to retrieve at a time.
searchRequest.source(searchSourceBuilder);
searchRequest.scroll(TimeValue.timeValueMinutes(1L)); // Set the scroll interval
SearchResponse searchResponse = client.search(searchRequest);
String scrollId = searchResponse.getScrollId(); // Read the returned scroll id, which points to the search context that’s being kept alive and will be needed in the following search scroll call
SearchHits hits = searchResponse.getHits(); // Retrieve the first batch of search hits
检索所有相关文档
其次, 接收到的滚动标识符必须被设置到下一个新的滚动间隔的 SearchScrollRequest, 并通过 searchScroll 方法发送。Elasticsearch会使用新的滚动标识符返回另一批结果。 然后可以在随后的SearchScrollRequest中使用此新的滚动标识符来检索下一批结果,等等。应该循环重复此过程,直到不再返回结果,这意味着滚动已经用尽,并且已经检索到所有匹配的文档。
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId); //Create the SearchScrollRequest by setting the required scroll id and the scroll interval
scrollRequest.scroll(TimeValue.timeValueSeconds(30));
SearchResponse searchScrollResponse = client.searchScroll(scrollRequest);
scrollId = searchScrollResponse.getScrollId(); // Read the new scroll id, which points to the search context that’s being kept alive and will be needed in the following search scroll call
hits = searchScrollResponse.getHits(); //Retrieve another batch of search hits <4>
assertEquals(3, hits.getTotalHits());
assertEquals(1, hits.getHits().length);
assertNotNull(scrollId);
清除滚动上下文
最后,可以使用Clear Scroll API删除最后一个滚动标识符,以释放搜索上下文。 当滚动到期时,会自动发生,但最佳实践是当滚动会话结束后尽快释放资源。
可选参数
构建 SearchScrollRequest 是可以选择使用以下参数:
scrollRequest.scroll(TimeValue.timeValueSeconds(60L)); // Scroll interval as a TimeValue
scrollRequest.scroll("60s"); // Scroll interval as a String
同步执行
SearchResponse searchResponse = client.searchScroll(scrollRequest);
异步执行
client.searchScrollAsync(scrollRequest, new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse searchResponse) {
// 当执行成功的时候调用,响应对象以参数的形式传入
}
@Override
public void onFailure(Exception e) {
// 失败时调用,异常以参数形式传入
}
});
响应
与 Search API 一样,滚动搜索 API 也返回一个 SearchResponse 对象
完整示例
下面是一个滚动搜索的完整示例:
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1L));
SearchRequest searchRequest = new SearchRequest("posts");
searchRequest.scroll(scroll);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(matchQuery("title", "Elasticsearch"));
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = client.search(searchRequest); // 通过发送初始化 SearchRequest 来初始化搜索上下文
String scrollId = searchResponse.getScrollId();
SearchHit[] searchHits = searchResponse.getHits().getHits();
while (searchHits != null && searchHits.length > 0) { //在一个循环中通过调用 Search Scroll api 检索所有搜索命中结果,知道没有文档返回为止。
//创建一个新的SearchScrollRequest,持有最近一次返回的滚动标识符和滚动间隔
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(scroll);
searchResponse = client.searchScroll(scrollRequest);
scrollId = searchResponse.getScrollId();
searchHits = searchResponse.getHits().getHits();
//处理返回的搜索结果
}
ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); //一旦滚动完成,清除滚动上下文
clearScrollRequest.addScrollId(scrollId);
ClearScrollResponse clearScrollResponse = client.clearScroll(clearScrollRequest);
boolean succeeded = clearScrollResponse.isSucceeded();