【1】Spring Data Elasticsearch
官网地址:https://spring.io/projects/spring-data-elasticsearch#learn,最新稳定版本为3.2.3。
开发文档地址:https://docs.spring.io/spring-data/elasticsearch/docs/3.2.3.RELEASE/reference/html/#reference
版本标识说明
GA:General Availability,正式发布的版本,官方推荐使用此版本。在国外都是用GA来说明release版本的。 PRE: 预览版,内部测试版. 主要是给开发人员和测试人员测试和找BUG用的,不建议使用; SNAPSHOT: 快照版,可以稳定使用,且仍在继续改进版本。
Spring Data Elasticsearch
版本新特性
Spring Data Elasticsearch 3.2引入了一下新特性:
Elasticsearch集群支持基本身份验证和SSL传输。
升级至Elasticsearch 6.8.1。
Reactive programming support with Reactive Elasticsearch Operations and Reactive Elasticsearch Repositories.
ElasticsearchEntityMapper作为Jackson对象映射器的替代品。
@Field中的字段名自定义。
支持按查询删除。
Reactive programming support with Reactive Elasticsearch Operations and Reactive Elasticsearch Repositories.这句话这样翻译:响应式的Elasticsearch Operations和响应式的Elasticsearch Repositories一起提供了响应式编程支持。
版本对应说明
Spring Data Release Train | Spring Data Elasticsearch | Elasticsearch | Spring Boot |
Moore | 3.2.x | 6.8.4 | 2.2.x |
Lovelace | 3.1.x | 6.2.2 | 2.1.x |
Kay | 3.0.x | 5.5.0 | 2.0.x |
Ingalls | 2.1.x | 2.4.0 | 1.5.x |
【2】Elasticsearch Clients
Spring data Elasticsearch 可以使用Elasticsearch 客户端连接到单一节点或者集群进行操作。
① Transport Client
在前面Java原生操作Elasticsearch我们就使用的是这个客户端,实话说,确实很难用。
static class Config { //首先得获取客户端 @Bean Client client() { Settings settings = Settings.builder() .put("cluster.name", "elasticsearch") .build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1") , 9300)); return client; } } // ...具体使用诸如下面代码 IndexRequest request = new IndexRequest("spring-data", "elasticsearch", randomID()) .source(someObject) .setRefreshPolicy(IMMEDIATE); IndexResponse response = client.index(request);
② High Level REST Client(高级REST客户端)
High Level REST Client现在是Elasticsearch默认客户端,它替换掉了Transport Client。异步调用在客户端管理的线程池上操作,并要求在请求完成时通知回调。
引入pom:
<dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.2.3.RELEASE</version> </dependency>
配置类:
@Configuration public class ElasticsearchConfig { @Bean RestHighLevelClient client() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("192.168.18.128:9200") // .connectedTo("192.168.18.128:9300", "localhost:9301") .build(); RestHighLevelClient restHighLevelClient = RestClients.create(clientConfiguration).rest(); System.out.println(restHighLevelClient); return restHighLevelClient; } }
测试代码:
@Autowired RestHighLevelClient highLevelClient; @Test public void test() throws IOException { GetRequest getRequest=new GetRequest("my-blog","_all","1"); RequestOptions option=RequestOptions.DEFAULT; GetResponse getResponse = highLevelClient.get(getRequest, option); System.out.println(getResponse.getIndex()); System.out.println(getResponse.toString()); }
控制台打印:
{ "_index": "my-blog", "_type": "article", "_id": "1", "_version": 1, "found": true, "_source": { "id": "1", "title": "基于Lucene的搜索服务器", "content": "它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口" } }
③ Reactive Client
ReactiveElasticsearchClient 是基于WebClient的非官方驱动程序,使用Elasticsearch 核心项目提供的request/response对象。调用直接在反应堆栈上操作,而不是将异步(线程池绑定)响应包装为反应类型。
示例代码如下:
static class Config { @Bean ReactiveElasticsearchClient client() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200", "localhost:9291") .build(); return ReactiveRestClients.create(clientConfiguration); } } // ... Mono<IndexResponse> response = client.index(request -> request.index("spring-data") .type("elasticsearch") .id(randomID()) .source(singletonMap("feature", "reactive-client")) .setRefreshPolicy(IMMEDIATE); );
④ Client Configuration
上面三个客户端对象都是通过ClientConfiguration对象创建出来的,客户端的行为可以通过该对象改变,也可以选择行的进行其他配置,如ssl。
示例代码:
// optional if Basic Auhtentication is needed HttpHeaders defaultHeaders = new HttpHeaders(); defaultHeaders.setBasicAuth(USER_NAME, USER_PASS); ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("localhost:9200", "localhost:9291") .withConnectTimeout(Duration.ofSeconds(5)) .withSocketTimeout(Duration.ofSeconds(3)) .useSsl() .withDefaultHeaders(defaultHeaders) .withBasicAuth(username, password) . // ... other options .build();
【3】Elasticsearch Object Mapping
Spring Data Elasticsearch允许在通过EntityMapper接口抽象的两个映射实现之间进行选择:
- Jackson Object Mapping
- Meta Model Object Mapping
① Jackson Object Mapping
基于Jackson2的方法(默认情况下使用)使用带有spring数据特定模块的自定义ObjectMapper实例。实际映射的扩展需要通过Jackson注释(比如@JsonInclude)进行定制。
示例代码:
@Configuration public class Config extends AbstractElasticsearchConfiguration { @Override public RestHighLevelClient elasticsearchClient() { return RestClients.create(ClientConfiguration.create("localhost:9200")).rest(); } }
AbstractElasticsearchConfiguration已经通过ElasticsearchConfigurationSupport定义了一个基于Jackson2的entityMapper。注意这时这些注解不能使用:CustomConversions, @ReadingConverter & @WritingConverter,并且@Field(name="custom-name")也不行。
② Meta Model Object Mapping
基于元模型的方法使用域类型信息来读/写Elasticsearch。这允许注册特定域类型映射的转换器实例。
示例代码;
@Configuration public class Config extends AbstractElasticsearchConfiguration { @Override public RestHighLevelClient elasticsearchClient() { return RestClients.create(ClientConfiguration.create("localhost:9200")).rest() } @Bean @Override public EntityMapper entityMapper() { ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper( elasticsearchMappingContext(), new DefaultConversionService() ); entityMapper.setConversions(elasticsearchCustomConversions()); return entityMapper; } }
说明:
覆盖掉ElasticsearchConfigurationSupport 默认配置的EntityMapper 并作为bean对外暴露;
Use the provided SimpleElasticsearchMappingContext to avoid inconsistencies and provide a GenericConversionService for Converter registration.
如果需要,可以设置CustomConversions
③ 对象映射注解
ElasticsearchEntityMapper可以使用元数据来驱动对象到文档的映射。对象上面可以使用注解进行标识。
@Id: 目标对象主键,字段级别注解。
@Document: 类级别注解,标明是个文档对象,有如下重要属性:
indexName: 实体中的索引名字
type: the mapping type.如果未设置,则使用类的小写简单名称。
shards: 索引分片数量
replicas: 索引的副本数
refreshIntervall: 索引的刷新间隔。用于创建索引。默认值为“1s”。
indexStoreType:索引存储类型。用于创建索引。默认值为“fs”。
createIndex: 配置是否在存储库引导时创建索引。默认值为true。
versionType: 版本管理的配置,默认值为 EXTERNAL.
@Transient: 默认所有字段都映射到document, 添加该注解的字段可以例外。
@PersistenceConstructor: 从数据库中实例化对象时,标记要使用的给定构造函数(甚至是受包保护的构造函数)。构造函数参数按名称映射到检索到的文档中的键值。
@Field: 应用于字段级别并定义字段的属性,大多数属性映射到相应的Elasticsearch Mapping定义:
name: field映射到Elasticsearch document中的名称,默认为字段名。
type: 字段类型,可以是如下之一: Text, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment, Keyword.
format and pattern custom definitions for the Date type.
store: 标记原始字段值是否应存储在Elasticsearch中,默认值为false。
analyzer, searchAnalyzer, normalizer用于指定自定义分析器和规范化器。
copy_to: 拷贝到多个文档字段的目标字段
@GeoPoint:将字段标记为地理位置数据类型。如果字段是GeoPoint类的实例,则可以忽略。
上述映射元数据注解定义在一个单独的spring-data-commons 项目中,是技术无关的。④ 映射规则
映射规则主要有四方面:
- Type Hints:按照类型映射;
- Geospatial Types:点和地质点等地理空间类型转换为纬度/经纬度对。
- Collections:对于集合内的值,当涉及类型提示和自定义转换时,将应用与聚合根相同的映射规则。
Maps:同Collections,但是键是需要是字符串
- Custom Conversions
可以使用ElasticsearchCustomConversions 注册自定义的映射规则,示例代码如下:
@Configuration public class Config extends AbstractElasticsearchConfiguration { @Override public RestHighLevelClient elasticsearchClient() { return RestClients.create(ClientConfiguration.create("localhost:9200")).rest(); } @Bean @Override public EntityMapper entityMapper() { ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper( elasticsearchMappingContext(), new DefaultConversionService()); entityMapper.setConversions(elasticsearchCustomConversions()); return entityMapper; } @Bean @Override public ElasticsearchCustomConversions elasticsearchCustomConversions() { return new ElasticsearchCustomConversions( Arrays.asList(new AddressToMap(), new MapToAddress())); } @WritingConverter static class AddressToMap implements Converter<Address, Map<String, Object>> { @Override public Map<String, Object> convert(Address source) { LinkedHashMap<String, Object> target = new LinkedHashMap<>(); target.put("ciudad", source.getCity()); // ... return target; } } @ReadingConverter static class MapToAddress implements Converter<Map<String, Object>, Address> { @Override public Address convert(Map<String, Object> source) { // ... return address; } } }
【4】Elasticsearch Operations
在第一部分描述新特性时,有个特性是Reactive programming support with Reactive Elasticsearch Operations and Reactive Elasticsearch Repositorie,这里不能简单翻译而要深入了解一下什么是Reactive Elasticsearch Operations、Reactive Elasticsearch Repositorie才能知道如何提供响应式编程支持。
Spring Data Elasticsearch使用两个接口来定义可以针对Elasticsearch索引调用的操作。分别是ElasticsearchOperations and ReactiveElasticsearchOperations。前者通常用于经典的同步实现,后者用于响应式编程。
接口的默认实现提供如下三方面功能:
- 对域类型的读/写映射支持。
- 一个丰富的查询和条件api。
- 资源管理和异常转换
① ElasticsearchTemplate
ElasticsearchTemplate是ElasticsearchOperations 接口的一个实现,是基于Transport Client操作的。
示例代码如下:
@Configuration public class TransportClientConfig extends ElasticsearchConfigurationSupport { @Bean public Client elasticsearchClient() throws UnknownHostException { Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build(); TransportClient client = new PreBuiltTransportClient(settings); client.addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); return client; } @Bean(name = {"elasticsearchOperations", "elasticsearchTemplate"}) public ElasticsearchTemplate elasticsearchTemplate() throws UnknownHostException { return new ElasticsearchTemplate(elasticsearchClient(), entityMapper()); } // use the ElasticsearchEntityMapper @Bean @Override public EntityMapper entityMapper() { ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(), new DefaultConversionService()); entityMapper.setConversions(elasticsearchCustomConversions()); return entityMapper; } }
② ElasticsearchRestTemplate
ElasticsearchRestTemplate是ElasticsearchOperations 接口的另一个实现,其是基于High Level REST Client.实现的。
配置代码示例如下:
@Configuration public class RestClientConfig extends AbstractElasticsearchConfiguration { @Override public RestHighLevelClient elasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("192.168.18.128:9200") .withSocketTimeout(60000) .withConnectTimeout(60000) .build(); RestHighLevelClient restHighLevelClient = RestClients.create(clientConfiguration).rest(); System.out.println("RestClientConfig-elasticsearchClient:"+restHighLevelClient); return restHighLevelClient; } // no special bean creation needed // use the ElasticsearchEntityMapper @Bean @Override public EntityMapper entityMapper() { ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(elasticsearchMappingContext(), new DefaultConversionService()); entityMapper.setConversions(elasticsearchCustomConversions()); return entityMapper; } }
③ Spring REST controller中使用ElasticsearchOperations
具体ElasticsearchOperations 使用哪种实现,主要依据上面两种配置。示例代码如下:
@RestController public class TestController { @Autowired private ElasticsearchOperations elasticsearchOperations; // public TestController(ElasticsearchOperations elasticsearchOperations) { // this.elasticsearchOperations = elasticsearchOperations; // } @PostMapping("/person") public String save(@RequestBody Person person) { System.out.println("elasticsearchOperations:"+elasticsearchOperations); IndexQuery indexQuery = new IndexQueryBuilder() .withId(person.getId().toString()) .withObject(person) .build(); String documentId = elasticsearchOperations.index(indexQuery); return documentId; } @GetMapping("/person/{id}") public Person findById(@PathVariable("id") Long id) { Person person = elasticsearchOperations .queryForObject(GetQuery.getById(id.toString()), Person.class); return person; } }
Person类实例代码:
@Document(indexName = "person",type = "person") public class Person { @Id private Integer id; @Field private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
上面两个都是ElasticsearchOperations 的实现,下面讲解Reactive Elasticsearch Operations实现。
④ Reactive Elasticsearch Operations
ReactiveElasticsearchOperations是Elasticsearch集群使用ReactiveElasticsearchClient执行高级命令的网关。ReactiveElasticsearchOperations的默认实现是ReactiveElasticsearchTemplate 。
示例代码如下:
@Configuration public class Config extends AbstractReactiveElasticsearchConfiguration { @Bean @Override public ReactiveElasticsearchClient reactiveElasticsearchClient() { // ... } }
使用ReactiveElasticsearchClient 最简单方法就是继承AbstractReactiveElasticsearchConfiguration 并覆盖reactiveElasticsearchClient方法,然后作为bean暴露给外部。方法体内部可以使用ReactiveRestClients 定义 Reactive Client或者默认使用DefaultReactiveElasticsearchClient。
如果想对组件有更多自定义控制,可以如下所示进行配置:
@Configuration public class Config { @Bean public ReactiveElasticsearchClient reactiveElasticsearchClient() { // ... } @Bean public ElasticsearchConverter elasticsearchConverter() { return new MappingElasticsearchConverter(elasticsearchMappingContext()); } @Bean public SimpleElasticsearchMappingContext elasticsearchMappingContext() { return new SimpleElasticsearchMappingContext(); } @Bean public ReactiveElasticsearchOperations reactiveElasticsearchOperations() { return new ReactiveElasticsearchTemplate(reactiveElasticsearchClient(), elasticsearchConverter()); } }
⑤ ReactiveElasticsearchTemplate实际使用
实例代码如下:
@Document(indexName = "marvel", type = "characters") public class Person { private @Id String id; private String name; private int age; // Getter/Setter omitted... }
template.save(new Person("Bruce Banner", 42)) .doOnNext(System.out::println) .flatMap(person -> template.findById(person.id, Person.class)) .doOnNext(System.out::println) .flatMap(person -> template.delete(person)) .doOnNext(System.out::println) .flatMap(id -> template.count(Person.class)) .doOnNext(System.out::println) .subscribe();
控制台打印:
> Person(id=QjWCWWcBXiLAnp77ksfR, name=Bruce Banner, age=42) > Person(id=QjWCWWcBXiLAnp77ksfR, name=Bruce Banner, age=42) > QjWCWWcBXiLAnp77ksfR > 0
可以发现相比于RestHighLevelClient 而言ReactiveElasticsearchTemplate主要就是流式编程,可以直接使用Lamda表达式及隐式函数进行操作。
【5】Elasticsearch Repositories
Repository,了解jpa的应该知道,Spring Data默认定义了一些接口实现了一些常用的增删改查方法,你只需要声明自己接口继承于Spring Data的接口即可使用那些方法且不用自己实现。当然,你可以自己实现自己定义方法。
① 查询方法与查询策略
Elasticsearch模块支持所有基本的查询构建功能,如字符串查询、本地索查询、基于条件的查询或从方法名派生。从方法名派生查询并不总是足够的,并且/或者可能导致无法读取方法名。在这种情况下,可以使用@Query注解。
通常,Elasticsearch的查询创建机制的工作方式如查询方法中所述,实例如下:
interface BookRepository extends Repository<Book, String> { List<Book> findByNameAndPrice(String name, Integer price); }
等同于如下Elasticsearch json 查询串:
{ "bool" : { "must" : [ { "field" : {"name" : "?"} }, { "field" : {"price" : "?"} } ] } }
Elasticsearch 支持的关键字与对应的json 查询列表如下:
Keyword | Sample | Elasticsearch Query String |
And | findByNameAndPrice | {“bool” : {“must” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}} |
② @Query注解
如果想自定义查询,可以选择在方法上用注解标识查询条件,实例如下:
interface BookRepository extends ElasticsearchRepository<Book, String> { @Query("{\"bool\" : {\"must\" : {\"field\" : {\"name\" : \"?0\"}}}}") Page<Book> findByName(String name,Pageable pageable); }
③ 基于注解的配置
Spring Data Elasticsearch repositories using JavaConfig,for example:
@Configuration @EnableElasticsearchRepositories( basePackages = "org.springframework.data.elasticsearch.repositories" ) static class Config { @Bean public ElasticsearchOperations elasticsearchTemplate() { // ... } } class ProductService { private ProductRepository repository; public ProductService(ProductRepository repository) { this.repository = repository; } public Page<Product> findAvailableBookByName(String name, Pageable pageable) { return repository.findByAvailableTrueAndNameStartingWith(name, pageable); } }
需要说明的是,EnableElasticsearchRepositories注解激活Repository 支持。如果没有配置基包( base package),则它将使用在任何添加该注解的配置类上。
④ Elasticsearch Repositories using CDI*
Spring Data Elasticsearch repositories同样支持CDI(上下文依赖注入)能力,实例如下:
class ElasticsearchTemplateProducer { @Produces @ApplicationScoped public ElasticsearchOperations createElasticsearchTemplate() { // ... } } class ProductService { private ProductRepository repository; public Page<Product> findAvailableBookByName(String name, Pageable pageable) { return repository.findByAvailableTrueAndNameStartingWith(name, pageable); } @Inject public void setRepository(ProductRepository repository) { this.repository = repository; } }
⑤ Spring applicationContext.xml中配置Elasticsearch
Setting up Elasticsearch repositories using Namespace:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/data/elasticsearch https://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd"> <elasticsearch:repositories base-package="com.acme.repositories" /> </beans>
Transport Client using Namespace:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/data/elasticsearch https://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd"> <elasticsearch:transport-client id="client" cluster-nodes="localhost:9300,someip:9300" /> </beans>
Rest Client using Namespace:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch" xsi:schemaLocation="http://www.springframework.org/schema/data/elasticsearch https://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <elasticsearch:rest-client id="restClient" hosts="http://localhost:9200"> </beans>
【6】Reactive Elasticsearch Repositories
Reactive Elasticsearch repository支持Spring Data Repositories核心接口扩展,通过Reactive Elasticsearch Operations实现(Reactive Client实际执行)。
Reactive Elasticsearch repository是使用Project Reactor作为其组件来实现响应编程。
有三个接口主要被使用:
- ReactiveRepository
- ReactiveCrudRepository
- ReactiveSortingRepository
① 配置ReactiveRepositoryConfig
@Configuration @EnableReactiveElasticsearchRepositories public class ReactiveRepositoryConfig extends AbstractReactiveElasticsearchConfiguration { @Override public ReactiveElasticsearchClient reactiveElasticsearchClient() { ClientConfiguration clientConfiguration = ClientConfiguration.builder() .connectedTo("192.168.18.128:9200") .withSocketTimeout(60000) .withConnectTimeout(60000) .build(); ReactiveElasticsearchClient reactiveElasticsearchClient = ReactiveRestClients.create(clientConfiguration); System.out.println("reactiveElasticsearchClient is created:"+reactiveElasticsearchClient); return reactiveElasticsearchClient; } }
② Domain Object
@Document(indexName = "person",type = "person") public class Person { @Id private String id; private String firstname; private String lastname; //... }
③ 自定义Repository接口继承自ReactiveSortingRepository
实例代码如下:
public interface ReactivePersonRepository extends ReactiveSortingRepository<Person, String> { Flux<Person> findByFirstname(String firstname); Flux<Person> findByFirstname(Publisher<String> firstname); Flux<Person> findByFirstnameOrderByLastname(String firstname); Flux<Person> findByFirstname(String firstname, Sort sort); Flux<Person> findByFirstname(String firstname, Pageable page); Mono<Person> findByFirstnameAndLastname(String firstname, String lastname); Mono<Person> findFirstByLastname(String lastname); @Query("{ \"bool\" : { \"must\" : { \"term\" : { \"lastname\" : \"?0\" } } } }") Flux<Person> findByLastname(String lastname); Mono<Long> countByFirstname(String firstname); Mono<Boolean> existsByFirstname(String firstname); Mono<Long> deleteByFirstname(String firstname); }
可以看到ReactiveSortingRepository又继承自ReactiveCrudRepository,故而当前ReactivePersonRepository 可以使用CRUD和Sort等方法。
④ 测试代码
@RestController public class ReactiveController { @Autowired ReactivePersonRepository repository; @RequestMapping("/testReactive") public String testReactive() { Flux<Person> persons = repository.findAll(); System.out.println(persons.blockFirst()); Mono<List<Person>> listMono = persons.collectList(); System.out.println("listMono:"+ listMono); List<Person> personList = listMono.block(); System.out.println("personList:"+personList); return persons.toString(); } }
【7】Miscellaneous Elasticsearch Operation Support
Elasticsearch Operation还提供了许多其他支持,而这些支持不能直接通过repository 接口来使用,它更被推荐在自定义接口实现里面使用。
① 查询过滤器
实例如下:
private ElasticsearchTemplate elasticsearchTemplate; SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(matchAllQuery()) .withFilter(boolFilter().must(termFilter("id", documentId))) .build(); Page<SampleEntity> sampleEntities = elasticsearchTemplate.queryForPage(searchQuery,SampleEntity.class);
② 滚动输出大结果集
Elasticsearch 针对大数据量结果提供了scroll API,ElasticsearchTemplate 有startScroll and continueScroll 方法可以被使用,如下所示:
SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(matchAllQuery()) .withIndices(INDEX_NAME) .withTypes(TYPE_NAME) .withFields("message") .withPageable(PageRequest.of(0, 10)) .build(); ScrolledPage<SampleEntity> scroll = elasticsearchTemplate.startScroll(1000, searchQuery, SampleEntity.class); String scrollId = scroll.getScrollId(); List<SampleEntity> sampleEntities = new ArrayList<>(); while (scroll.hasContent()) { sampleEntities.addAll(scroll.getContent()); scrollId = scroll.getScrollId(); scroll = elasticsearchTemplate.continueScroll(scrollId, 1000, SampleEntity.class); } elasticsearchTemplate.clearScroll(scrollId);
ElasticsearchTemplate 同样提供了流方法使用,如下所示:
SearchQuery searchQuery = new NativeSearchQueryBuilder() .withQuery(matchAllQuery()) .withIndices(INDEX_NAME) .withTypes(TYPE_NAME) .withFields("message") .withPageable(PageRequest.of(0, 10)) .build(); CloseableIterator<SampleEntity> stream = elasticsearchTemplate.stream(searchQuery, SampleEntity.class); List<SampleEntity> sampleEntities = new ArrayList<>(); while (stream.hasNext()) { sampleEntities.add(stream.next()); }
相关实例代码GitHub地址:https://github.com/JanusJ/SpringBoot/tree/master/elasticsearch