Spring Data Elasticsearch基础入门详解

简介: Spring Data Elasticsearch基础入门详解

【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” : “?”}} ]}}

4.png5.png6.png


② @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

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。 &nbsp;
目录
相关文章
|
2月前
|
NoSQL Java 数据库连接
《深入理解Spring》Spring Data——数据访问的统一抽象与极致简化
Spring Data通过Repository抽象和方法名派生查询,简化数据访问层开发,告别冗余CRUD代码。支持JPA、MongoDB、Redis等多种存储,统一编程模型,提升开发效率与架构灵活性,是Java开发者必备利器。(238字)
|
2月前
|
存储 Java 关系型数据库
Spring Boot中Spring Data JPA的常用注解
Spring Data JPA通过注解简化数据库操作,实现实体与表的映射。常用注解包括:`@Entity`、`@Table`定义表结构;`@Id`、`@GeneratedValue`配置主键策略;`@Column`、`@Transient`控制字段映射;`@OneToOne`、`@OneToMany`等处理关联关系;`@Enumerated`、`@NamedQuery`支持枚举与命名查询。合理使用可提升开发效率与代码可维护性。(238字)
337 1
|
2月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
449 2
存储 JSON Java
545 0
|
3月前
|
SQL Java 数据库连接
Spring Data JPA 技术深度解析与应用指南
本文档全面介绍 Spring Data JPA 的核心概念、技术原理和实际应用。作为 Spring 生态系统中数据访问层的关键组件,Spring Data JPA 极大简化了 Java 持久层开发。本文将深入探讨其架构设计、核心接口、查询派生机制、事务管理以及与 Spring 框架的集成方式,并通过实际示例展示如何高效地使用这一技术。本文档约1500字,适合有一定 Spring 和 JPA 基础的开发者阅读。
406 0
|
5月前
|
前端开发 Java API
基于 Spring Boot 3 与 React 的 Java 学生信息管理系统从入门到精通实操指南
本项目基于Spring Boot 3与React 18构建学生信息管理系统,涵盖前后端开发、容器化部署及测试监控,提供完整实操指南与源码,助你掌握Java全栈开发技能。
282 0
|
5月前
|
NoSQL Java Redis
Redis基本数据类型及Spring Data Redis应用
Redis 是开源高性能键值对数据库,支持 String、Hash、List、Set、Sorted Set 等数据结构,适用于缓存、消息队列、排行榜等场景。具备高性能、原子操作及丰富功能,是分布式系统核心组件。
599 2
|
6月前
|
Java API 微服务
Java 21 与 Spring Boot 3.2 微服务开发从入门到精通实操指南
《Java 21与Spring Boot 3.2微服务开发实践》摘要: 本文基于Java 21和Spring Boot 3.2最新特性,通过完整代码示例展示了微服务开发全流程。主要内容包括:1) 使用Spring Initializr初始化项目,集成Web、JPA、H2等组件;2) 配置虚拟线程支持高并发;3) 采用记录类优化DTO设计;4) 实现JPA Repository与Stream API数据访问;5) 服务层整合虚拟线程异步处理和结构化并发;6) 构建RESTful API并使用Springdoc生成文档。文中特别演示了虚拟线程配置(@Async)和StructuredTaskSco
792 0
|
7月前
|
JSON 安全 数据可视化
Elasticsearch(es)在Windows系统上的安装与部署(含Kibana)
Kibana 是 Elastic Stack(原 ELK Stack)中的核心数据可视化工具,主要与 Elasticsearch 配合使用,提供强大的数据探索、分析和展示功能。elasticsearch安装在windows上一般是zip文件,解压到对应目录。文件,elasticsearch8.x以上版本是自动开启安全认证的。kibana安装在windows上一般是zip文件,解压到对应目录。elasticsearch的默认端口是9200,访问。默认用户是elastic,密码需要重置。
3765 0
|
8月前
|
安全 Java Linux
Linux安装Elasticsearch详细教程
Linux安装Elasticsearch详细教程
1500 64