Github源码:
https://github.com/Mengzuozhu/es-demo
相关文章链接:
ES分页方式对比
参考:
https://blog.csdn.net/andybegin/article/details/83864171
分页方式 | 简述 | 缺点 |
---|---|---|
from size | 浅分页情况下,可以考虑使用; | 深度分页情况下,性能较差 |
Scroll | 基于历史快照和上一页的scroll_id,查询下一页; | ● 滚屏翻页,快照比较占内存; ● 不适合实时搜索和跳页需求 |
Search After | 1. 需要排序,官方(5.6版本 )推荐使用 _uid 作为排序字段和全局唯一值(注:不同版本的ES,官方文档有变动,请参考对应版本的文档。比如,7.x版本 建议拷贝_id 字段值到另外一个支持doc value 的字段,用于作为排序字段);2. 通过实时cursor来规避耗时和占存储的性能问题,基于上一页的结果帮助检索下一页; 3. 使用search_after参数时,from的值必须为0或者-1 | ● 需要排序; ● 不适合跳页需求 |
注:在7.x官方文档中,已不太建议使用Scroll API来深分页了https://www.elastic.co/guide/en/elasticsearch/reference/7.x/paginate-search-results.html#scroll-search-results
Java代码示例
ES 5.6.8版本
maven引用
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
Search After 的Java代码示例
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.function.Consumer;
public class EsSearchAfterHandler {
private static final String UID = "_uid";
public static void main(String[] args) throws UnknownHostException {
// example: 127.0.0.1
String esIp = "your es ip";
TransportClient esClient = buildEsTransportClient("elasticsearch", esIp, 9301);
int batchSize = 1000;
SearchRequestBuilder searchRequestBuilder = esClient.prepareSearch("your index")
.setQuery(QueryBuilders.matchAllQuery())
.setSize(batchSize);
EsSearchAfterHandler.searchForHit(searchRequestBuilder, searchHit -> {
// your code ...
// example:
System.out.println(searchHit.getSourceAsString());
});
}
/**
* Search for hit.
*
* @param requestBuilder the request builder
* @param consumer the consumer
*/
public static void searchForHit(SearchRequestBuilder requestBuilder, Consumer<SearchHit> consumer) {
searchForResponse(requestBuilder, searchResponse -> {
SearchHit[] searchHits = searchResponse.getHits().getHits();
for (SearchHit searchHit : searchHits) {
consumer.accept(searchHit);
}
});
}
/**
* Search for response.
*
* @param requestBuilder the request builder
* @param consumer the consumer
*/
public static void searchForResponse(SearchRequestBuilder requestBuilder, Consumer<SearchResponse> consumer) {
if (requestBuilder == null || consumer == null) {
return;
}
//requestBuilder.setSize(100); //在构建查询条件时,即可设置大小
//设置排序字段
SearchRequestBuilder sortBuilder = requestBuilder.addSort(UID, SortOrder.ASC);
SearchResponse searchResponse = sortBuilder.get();
SearchHit[] searchHits = searchResponse.getHits().getHits();
while (searchHits.length > 0) {
consumer.accept(searchResponse);
SearchHit last = searchHits[searchHits.length - 1];
sortBuilder = sortBuilder.searchAfter(last.getSortValues());
searchResponse = sortBuilder.get();
searchHits = searchResponse.getHits().getHits();
}
}
private static TransportClient buildEsTransportClient(String esCluster, String esIp, Integer esPort)
throws UnknownHostException {
Settings esSettings = Settings.builder()
.put("cluster.name", esCluster)
.build();
return new PreBuiltTransportClient(esSettings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(esIp), esPort));
}
}
ES 7.9.2版本
maven引用
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.9.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.9.2</version>
</dependency>
Search After 的Java代码示例
/**
* ES Search After查询
*
* @author zuozhu.meng
**/
public class EsSearchAfterHandler {
private static final String UID = "_id";
/**
* Search for hit.
*
* @param searchRequest the search request
* @param consumer the consumer
*/
public static void searchForHit(RestHighLevelClient client, SearchRequest searchRequest,
Consumer<SearchHit> consumer) throws IOException {
searchForResponse(client, searchRequest, searchResponse -> forEachHits(searchResponse, consumer));
}
/**
* Search for response.
*
* @param searchRequest the search request
* @param consumer the consumer
*/
public static void searchForResponse(RestHighLevelClient client, SearchRequest searchRequest,
Consumer<SearchResponse> consumer) throws IOException {
if (searchRequest == null || consumer == null) {
return;
}
SearchSourceBuilder sourceBuilder = searchRequest.source();
// sourceBuilder.size(100); //在构建查询条件时,即可设置大小
//设置排序字段
sourceBuilder.sort(UID, SortOrder.ASC);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
SearchHit[] searchHits = searchResponse.getHits().getHits();
while (searchHits.length > 0) {
consumer.accept(searchResponse);
SearchHit last = searchHits[searchHits.length - 1];
sourceBuilder.searchAfter(last.getSortValues());
searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
searchHits = searchResponse.getHits().getHits();
}
}
public static void forEachHits(SearchResponse searchResponse, Consumer<SearchHit> consumer) {
if (searchResponse == null) {
return;
}
SearchHit[] searchHits = searchResponse.getHits().getHits();
for (SearchHit searchHit : searchHits) {
consumer.accept(searchHit);
}
}
}