当前位置:   article > 正文

es中3种分页的介绍以及对比_es 分页

es 分页

一 es的3种分页对比

1.1 先上结论

类型

原理

优点

缺点

使用场景

from + size

类似 msql的 limit 0,100;  limit  from,size

灵活性好,实现简单,适合浅分页

无法实现深度分页问题,当查询数量超过10000就会报错

top10000以内的查询

Scroll

首次查询会在内存中保存一个历史快照以及游标(scroll_id),记录当前消息查询的终止位置,下次查询的时候将基于游标进行消费(不管while语句循环多少次,scrollid在设置的时效内,使用的是同一个),不具备实时性,一般是用于大量数据导出。

适合深分页

无法反应数据的实时性(快照版本),维护成本高,需要维护一个 scroll_id

最适合离线场景,海量数据的导出(比如笔者刚遇到的将es中20w的数据导入到excel),需要查询海量结果集的数据

Search After

step1:在查询第1页的时候,设置全局唯一性的字段进行组合排序;step2:查询数据之后,取出最后一笔数据的sort值,传到search_after进行查询;

step3:基于上一笔的sort值,查询排在它之后的数据,以此来实现分页

性能最好,适合深分页,能够反映数据的实时变更

不能够随机跳转分页,只能是一页一页的向后翻(当有新数据进来,也能实时查询到),并且需要至少指定一个唯一不重复字段来排序(一般是_id和时间字段)   

海量数据的实时分页

二  es的深度分页介绍

2.1 scroll分页

由于项目现场涉密,所写代码,只能截图还原;

1.初始化客户端

2.scroll查询数据

 2.参考此代码

  1. /**
  2. * 这种常用于根据筛选条件之后抽取全部数据的场景,
  3. * scroll API 可以被用来检索大量的结果, 甚至所有的结果 ,
  4. * 注意es的游标查询的是当下时刻的数据快照,
  5. * 即在游标查询之后的数据的变动不会影响游标查询的结果,
  6. * 默认游标查询根据_doc字段进行排序
  7. *
  8. * @param restHighLevelClient
  9. * @param indexName
  10. * @param typeName
  11. * @throws IOException
  12. */
  13. public static void cusorSearch(RestHighLevelClient restHighLevelClient, String indexName, String typeName) throws IOException {
  14. SearchRequest searchRequest = new SearchRequest(indexName, typeName);
  15. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.rangeQuery("price").gte(5.0).lte(100.0));
  16. searchSourceBuilder.size(2);
  17. searchRequest.source(searchSourceBuilder);
  18. Scroll scroll = new Scroll(timeValueMillis(1L));
  19. /**
  20. *
  21. * 在搜索条件之后使用searchSourceBuilder.size(2)设置了每次游标只抽取2条数据,
  22. * 设置每次游标的超时时间是1毫秒timeValueMillis,可以适当调高超时时间防止由于超时还没查完导致游标提前结束。
  23. * 在执行游标的时候,第一次使用了客户端的search方法,从第二次开始使用scroll方法,
  24. * 每开始下一次游标的时候都通过查看本次游标的结果是否为空searchResponse.getHits().getHits()来判断是否还要继续,
  25. * 把每次游标的返回结果收集起来拿到全部数据
  26. *
  27. */
  28. searchRequest.scroll(scroll);
  29. SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  30. String scrollId = searchResponse.getScrollId();
  31. SearchHit[] hits = searchResponse.getHits().getHits();
  32. List<SearchHit> resultSearchHit = new ArrayList<>();
  33. while (hits != null && hits.length > 0) {
  34. System.out.println(hits.length);
  35. System.out.println(scrollId);
  36. resultSearchHit.addAll(Arrays.asList(hits));
  37. SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
  38. searchScrollRequest.scroll(scroll);
  39. SearchResponse searchScrollResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
  40. scrollId = searchScrollResponse.getScrollId();
  41. hits = searchScrollResponse.getHits().getHits();
  42. }
  43. ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
  44. clearScrollRequest.addScrollId(scrollId);
  45. restHighLevelClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
  46. restHighLevelClient.close();
  47. }

 3.RestHighLevelClient 操作ElasticSearch-CSDN博客

2.2 search After分页

1.代码截图

 2.参考代码

  1. public static void main(String[] args) throws Exception{
  2. long startTime = System.currentTimeMillis();
  3. // 创建ES客户端
  4. RestHighLevelClient esClient = new RestHighLevelClient(
  5. RestClient.builder(new HttpHost("localhost", 9200, "http"))
  6. );
  7. // 1、创建searchRequest
  8. SearchRequest searchRequest = new SearchRequest("audit2");
  9. // 2、指定查询条件
  10. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder().trackTotalHits(true);//必须加上track_total_hits,不然就只显示10000
  11. //设置每页查询的数据个数
  12. sourceBuilder.size(1000);
  13. // 设置唯一排序值定位
  14. sourceBuilder.sort(SortBuilders.fieldSort("operationtime").order(SortOrder.DESC));//多条件查询
  15. //将sourceBuilder对象添加到搜索请求中
  16. searchRequest.source(sourceBuilder);
  17. // 发送请求
  18. SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
  19. SearchHit[] hits1 = searchResponse.getHits().getHits();
  20. List<Map<String, Object>> result = new ArrayList<>();
  21. if (hits1 != null && hits1.length > 0) {
  22. do {
  23. for (SearchHit hit : hits1) {
  24. // 获取需要数据
  25. Map<String, Object> sourceAsMap = hit.getSourceAsMap();
  26. result.add(sourceAsMap);
  27. }
  28. // 取得最后得排序值sort,用于记录下次将从这个地方开始取数
  29. SearchHit[] hits = searchResponse.getHits().getHits();
  30. Object[] lastNum = hits[hits.length - 1].getSortValues();
  31. // 设置searchAfter的最后一个排序值
  32. sourceBuilder.searchAfter(lastNum);
  33. searchRequest.source(sourceBuilder);
  34. // 进行下次查询
  35. searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
  36. } while (searchResponse.getHits().getHits().length != 0);
  37. }
  38. logger.info("查询出来的数据个数为:{}", result.size());
  39. // 关闭客户端
  40. esClient.close();
  41. logger.info("运行时间: " + (System.currentTimeMillis() - startTime) + "ms");
  42. }

【es】java使用es中三种查询用法from size、search after、scroll_es from size_致最长的电影的博客-CSDN博客

2.3 search After模拟前端分页查询 

原理:每次查询本次最后一条数据的sort值存储起来,返回给前端,下一页的时候,携带此sort值,开启下一页查询,传给searchBuilder。searchAfter(xxx)。

截图代码第1部分

截图代码第2部分

 3.调用

 4.es查询

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/619937
推荐阅读
相关标签
  

闽ICP备14008679号