spring-data-elasticsearch使用search_after  
        
      
     
    
   
   
最近防疫项目用到es做人员扫码快速检索能力,且es是集群部署,所以在深度分页这一块采用search_after的方式,项目采用spring-cloud开发,所以自然考虑使用spring-data-elasticsearch来操作es,过程中遇到一些坑,分享出来希望对大家有些帮助。
 
当然,先说正常的使用。 引入依赖,这里直接使用starter 1 2 3 4 5 <dependency >     <groupId > org.springframework.boot</groupId >      <artifactId > spring-boot-starter-data-elasticsearch</artifactId >      <version > 2.7.4</version >  </dependency > 
 
application.properties 1 2 3 4 5 6 7 8 9 spring.application.name =springdataesdemo spring.elasticsearch.rest.uris =172.29.0.22:31853 spring.elasticsearch.rest.connection-timeout =1000 spring.elasticsearch.rest.password =123456 spring.elasticsearch.rest.username =elastic server.port =8082 
 
实体类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package  org.example.springdataelasticsearch.entity;import  org.springframework.data.annotation.Id;import  org.springframework.data.elasticsearch.annotations.Document;import  org.springframework.data.elasticsearch.annotations.Field;@Data @Document(indexName = "record", createIndex = false) public  class  Record  {         @Id      private  String id;          private  String username;          @Field(name = "create_time")      private  String createTime; 
 
单元测试 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 package  org.example.springdataelasticsearch;import  org.example.springdataelasticsearch.entity.Record;import  org.junit.jupiter.api.Test;import  org.springframework.beans.factory.annotation.Autowired;import  org.springframework.boot.test.context.SpringBootTest;import  org.springframework.data.domain.PageRequest;import  org.springframework.data.domain.Sort;import  org.springframework.data.elasticsearch.core.ElasticsearchOperations;import  org.springframework.data.elasticsearch.core.SearchHit;import  org.springframework.data.elasticsearch.core.SearchHits;import  org.springframework.data.elasticsearch.core.query.Query;import  java.util.ArrayList;import  java.util.List;import  java.util.stream.Collectors;@SpringBootTest public  class  RecordTest  {    @Autowired      private  ElasticsearchOperations operations;     @Test      void  searchAfter () {         Query  query  =  Query.findAll();         query.setPageable(PageRequest.of(0 , 3 ));         query.addSort(Sort.by(Sort.Direction.ASC, "create_time" ));         List<Object> searchAfter = null ;         List<Record> foundEntities = new  ArrayList <>();         int  index  =  0 ;         do  {             query.setSearchAfter(searchAfter);             SearchHits<Record> searchHits = operations.search(query, Record.class);             if  (index++ == 10  || searchHits.getSearchHits().isEmpty()){                 break ;             }             foundEntities.addAll(searchHits.stream().map(SearchHit::getContent).collect(Collectors.toList()));             searchAfter = searchHits.getSearchHit((int ) (searchHits.getSearchHits().size() - 1 )).getSortValues();         }while  (true );         System.out.println(foundEntities);         System.out.println(searchAfter);     } } 
 
至此翻页就可以正常使用了
 
下面是一些踩坑点 1.通过观察spring-data-elasticsearch的源码可以知道search_after能力在4.2版本才开始支持,所以此版本之前Query类中是没有setSearchAfter()方法的,如果使用的是spring-boot-starter-data-elasticsearch,那要注意其中的spring-data-elasticsearch版本有没有到达4.2。 源码位置:https://github.com/spring-projects/spring-data-elasticsearch/blob/4.2.x/src/main/java/org/springframework/data/elasticsearch/core/query/Query.java 
1 2 3 4 5 6 7 8  void  setSearchAfter (@Nullable  List<Object> searchAfter) ; 
 
2.与Spring Boot版本对应错误导致spring-boot-starter-data-elasticsearch中spring-data-elasticsearch版本错误问题 如果你的pom文件中继承的spring-boot-starter-parent版本小于2.5.0,那么哪怕你引入的spring-boot-starter-data-elasticsearch版本是2.7.x,spring-data-elasticsearch还是会低于4.2.x,导致Query类中是没有setSearchAfter()方法: 可以通过将spring-boot-starter-parent的版本升级到2.5.x来解决这个问题,如果你的项目模块较多,或者什么原因升级版本有些麻烦,那么可以通过显示的添加指定版本的依赖来解决这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <dependency >     <groupId > org.springframework.boot</groupId >      <artifactId > spring-boot-starter-data-elasticsearch</artifactId >      <version > 2.7.4</version >      <exclusions >          <exclusion >              <artifactId > spring-data-elasticsearch</artifactId >              <groupId > org.springframework.data</groupId >          </exclusion >      </exclusions >  </dependency > <dependency >     <groupId > org.springframework.data</groupId >      <artifactId > spring-data-elasticsearch</artifactId >      <version > 4.4.3</version >      <scope > compile</scope >  </dependency > <dependency >     <groupId > org.springframework.data</groupId >      <artifactId > spring-data-commons</artifactId >      <version > 2.7.3</version >  </dependency > 
 
官方的版本对应关系图 附上传送地址:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.versions