Elasticsearch search after分页查询案例分享

bboss

Elasticsearch search after分页查询案例分享

1.准备工作

参考文档《高性能elasticsearch ORM开发库使用介绍》导入和配置es客户端

2.编写创建索引表和初始化数据方法

创建索引表和初始化数据的组件DocumentCRUD 实现本文不做重点介绍,请访问视频教程了解:

  1. /**
  2. * 创建索引表并导入测试数据
  3. */
  4. public void initIndiceAndData(){
  5. DocumentCRUD documentCRUD = new DocumentCRUD();
  6. documentCRUD.testCreateIndice();//创建索引表
  7. documentCRUD.testBulkAddDocuments();//导入测试数据
  8. }

3.定义searchAfter dsl配置文件

新建配置文件-esmapper/searchafter.xml

定义searchAfterDSL

  1. <properties>
  2. <property name="searchAfterDSL">
  3. <![CDATA[{
  4. #*
  5. 以demoId,_uid为searchAfter的分页条件 _uid值格式type#_id 由索引类型加#号加id拼接而成
  6. 如果按照多个字段的值做searchAter分页,则用逗号分隔每个值
  7. *#
  8. #if($searchAfterId) ## 第一次检索的时候,没有searchAfterId变量,只有做翻页操作的时候才会传递代表分页起点的searchAfterId变量进来
  9. "search_after": [#[demoId],"demo#[searchAfterId,quoted=false,lpad=#]"],
  10. #end
  11. "size": $pageSize, ##searchAfter分页每页最多显示的记录条数
  12. #*
  13. searchAfter分页检索时,必须用翻页字段作为排序字段,这里是demoId和_uid两个字段,如果是多个字段,则按照searchAfter的顺序来设置对应的排序属性
  14. *#
  15. "sort": [
  16. {"demoId": "asc"},
  17. {"_uid": "asc"}
  18. ],
  19. ## 其他检索条件,按照时间范围查询数据,所有数据按照上面的searchAter机制进行分页
  20. "query": {
  21. "bool": {
  22. "filter": [
  23. {
  24. "range": {
  25. "agentStarttime": {
  26. "gte": #[startTime],
  27. "lt": #[endTime]
  28. }
  29. }
  30. }
  31. ]
  32. }
  33. }
  34. }]]>
  35. </property>
  36. </properties>

4.定义实现searchAfter的代码

  1. public void doSeachAfter() throws ParseException {
  2. //创建加载配置文件的客户端工具,用来检索文档,单实例多线程安全
  3. ClientInterface clientUtil = ElasticSearchHelper.getConfigRestClientUtil("esmapper/searchafter.xml");
  4. Map params = new HashedMap();//定义检索条件,将dsl中需要的参数放置到params中
  5. params.put("pageSize",100);
  6. DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  7. params.put("startTime",dateFormat.parse("2017-09-02 00:00:00").getTime());
  8. params.put("endTime",new Date().getTime());
  9. //执行查询,demo为索引表,_search为检索操作action
  10. ESDatas<Demo> esDatas = //ESDatas包含当前检索的记录集合,最多1000条记录,由dsl中的size属性指定
  11. clientUtil.searchList("demo/_search",//demo为索引表,_search为检索操作action
  12. "searchAfterDSL",//esmapper/demo.xml中定义的dsl语句
  13. params,//变量参数
  14. Demo.class);//返回的文档封装对象类型
  15. //获取结果对象列表,最多返回1000条记录
  16. List<Demo> demos = esDatas.getDatas();
  17. //获取总记录数
  18. long totalSize = esDatas.getTotalSize();
  19. do{
  20. if(demos != null)
  21. System.out.println("返回当前页记录数:"+demos.size());
  22. if(demos != null && demos.size() == 100) { //还有数据,则通过searchAfter继续获取下一页数据
  23. String searchAfterId = (String) demos.get(99).getId();//获取最后一条记录的_id值
  24. params.put("searchAfterId", searchAfterId);//设置searchAfterId为分页起点_id值
  25. long demoId = demos.get(99).getDemoId();//获取最后一条记录的demoId值
  26. params.put("demoId", demoId);//设置searchAfterId为分页起点demoId值
  27. esDatas = //ESDatas包含当前检索的记录集合,最多1000条记录,由dsl中的size属性指定
  28. clientUtil.searchList("demo/_search",//demo为索引表,_search为检索操作action
  29. "searchAfterDSL",//esmapper/demo.xml中定义的dsl语句
  30. params,//变量参数
  31. Demo.class);//返回的文档封装对象类型
  32. demos = esDatas.getDatas();
  33. }
  34. else{//如果是最后一页,没有数据返回或者获取的记录条数少于100结束分页操作
  35. break;
  36. }
  37. }while(true);
  38. System.out.println("总记录数:"+totalSize);
  39. }

5.通过junit单元测试用例运行案例

  1. @Test
  2. public void testSeachAfter() throws ParseException {
  3. DocumentSearchAfter documentSearchAfter = new DocumentSearchAfter();
  4. documentSearchAfter.initIndiceAndData();//创建索引表并导入searchAfter分页测试数据
  5. documentSearchAfter.doSeachAfter();//执行searchAfter分页操作
  6. }

6.参考文档

https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-search-after.html

案例对应源码工程:

https://gitee.com/bboss/eshelloword

elasticsearch技术交流群:166471282

bboss elasticsearch微信公众号:

bboss微信公众号:bbossgroups