SpringElasticsearch


 Spring-Elasticsearch官方文档:https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#reference

  Spring Data Elasticsearch 在连接到单个 Elasticsearch 节点或集群的 Elasticsearch 客户端上运行。

  尽管 Elasticsearch Client 可用于与集群一起工作,但使用 Spring Data Elasticsearch 的应用程序通常使用  Elasticsearch Operations and Elasticsearch Repositories 的更高级别抽象

  Spring-data-elasticsearch依赖:

        
            org.springframework.boot
            spring-boot-starter-data-elasticsearch
            2.6.2
        

一、客户端

  Spring官方强烈建议使用使用 High Level REST Client 而不是 TransportClient,TransportClient 自 Elasticsearch 7 起已弃用,并将在 Elasticsearch 8 中删除

  1、TransportClient(弃用)

@Configuration
public class TransportClientConfig extends ElasticsearchConfigurationSupport {

    @Bean
    public Client elasticsearchClient() throws UnknownHostException {
       // 必须使用集群名称配置 TransportClient。
        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 {

        ElasticsearchTemplate template = new ElasticsearchTemplate(elasticsearchClient, elasticsearchConverter);
     // RefreshPolicy 必须在 ElasticsearchTemplate 中设置(覆盖 refreshPolicy() 以不使用默认值)
        template.setRefreshPolicy(refreshPolicy());                                                 

        return template;
    }
}

// 使用

IndexRequest request = new IndexRequest("spring-data")
 .id(randomID())
 .source(someObject);

IndexResponse response = client.index(request);    

  2、 High Level REST Client(高级REST客户端,推荐使用)

  Java High Level REST Client 是 Elasticsearch 的默认客户端,它提供了对 TransportClient 的直接替代,因为它接受并返回完全相同的请求/响应对象,因此依赖于 Elasticsearch 核心项目。异步调用在客户端管理的线程池上进行操作,并且需要在请求完成时通知回调

    1)配置

@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {

    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
     // 使用构建器提供集群地址、设置默认 HttpHeaders 或启用 SSL
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()  
            .connectedTo("localhost:9200")
            .build();
     // 创建高级REST客户端并返回
        return RestClients.create(clientConfiguration).rest();                         
    }
}

    2)使用

  @Autowired
  RestHighLevelClient highLevelClient;

  RestClient lowLevelClient = highLevelClient.lowLevelClient();                        

// ...

IndexRequest request = new IndexRequest("spring-data")
  .id(randomID())
  .source(singletonMap("feature", "high-level-rest-client"))
  .setRefreshPolicy(IMMEDIATE);

IndexResponse response = highLevelClient.index(request,RequestOptions.DEFAULT);

   3、 Reactive Client

    ReactiveElasticsearchClient 是一个基于 WebClient 的非官方驱动。它使用 Elasticsearch 核心项目提供的请求/响应对象。调用直接在响应式堆栈上操作,而不是将异步(线程池绑定)响应包装到响应式类型中。

@Configuration
public class ReactiveRestClientConfig extends AbstractReactiveElasticsearchConfiguration {

    @Override
    @Bean
    public ReactiveElasticsearchClient reactiveElasticsearchClient() {
      // 使用构建器提供集群地址、设置默认 HttpHeaders 或启用 SSL
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder() 
            .connectedTo("localhost:9200") //
            .build();
        return ReactiveRestClients.create(clientConfiguration);

    }
}
// ...

Mono response = client.index(request ->

  request.index("spring-data")
    .id(randomID())
    .source(singletonMap("feature", "reactive-client"));
); 

二、客户端配置

  客户端行为可以通过允许设置 SSL 选项、连接和套接字超时、标头和其他参数的 ClientConfiguration 进行更改

HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("some-header", "on every request")                      

ClientConfiguration clientConfiguration = ClientConfiguration.builder()
  .connectedTo("localhost:9200", "localhost:9291")               // 使用构建器提供集群地址、设置默认 HttpHeaders 或启用 SSL。       
  .usingSsl()                                                    // 可选择启用 SSL       
  .withProxy("localhost:8888")                                   // (可选)设置代理       
  .withPathPrefix("ela")                                         // 可选地设置路径前缀,主要用于在某些反向代理后面的不同集群时       
  .withConnectTimeout(Duration.ofSeconds(5))                     // 设置连接超时,默认是10秒       
  .withSocketTimeout(Duration.ofSeconds(3))                      // 设置socket超时,默认是5秒
  .withDefaultHeaders(defaultHeaders)                            // 可选地设置header       
  .withBasicAuth(username, password)                             // 添加基本??身份验证        
  .withHeaders(() -> {                                           // 可以指定一个 Supplier
函数,每次在请求发送到 Elasticsearch 之前都会调用该函数 - 例如,当前时间被写入header中 HttpHeaders headers = new HttpHeaders(); headers.add("currentTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); return headers; }) .withClientConfigurer( // 用于响应式设置配置 WebClient 的功能 ReactiveRestClients.WebClientConfigurationCallback.from(webClient -> { // ... return webClient; })) .withClientConfigurer( // 对于非反应式设置,配置 REST 客户端的功能 RestClients.RestClientConfigurationCallback.from(clientBuilder -> { // ... return clientBuilder; })) . // ... other options .build();

 客户端日志:

  要查看实际发送到服务器和从服务器接收的内容,需要打开传输级别的请求/响应日志记录,如:

<logger name="org.springframework.data.elasticsearch.client.WIRE" level="trace"/>

三、Elasticsearch操作 

  Spring Data Elasticsearch 使用多个接口来定义可以针对 Elasticsearch 索引调用的操作

    IndexOperations:定义索引级别的操作,例如创建或删除索引

    DocumentOperations:定义操作以根据实体 ID 存储、更新和检索实体

    SearchOperations定义使用查询搜索多个实体的操作

    ElasticsearchOperations:结合了 DocumentOperations 和 SearchOperations 接口

  1、ElasticsearchTemplate

    自 4.0 版起,不推荐使用 ElasticsearchTemplate,请改用 ElasticsearchRestTemplate

    ElasticsearchTemplate 是使用Transport Client的 ElasticsearchOperations 接口的实现

  2、ElasticsearchRestTemplate

    ElasticsearchRestTemplate 是使用高级 REST 客户端的 ElasticsearchOperations 接口的实现

    ElasticsearchRestTemplate配置:

@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
  @Override
  public RestHighLevelClient elasticsearchClient() {      
  // 设置高级 REST 客户端 
    return RestClients.create(ClientConfiguration.localhost()).rest();
  }

  // no special bean creation needed  
 // 基类 AbstractElasticsearchConfiguration 已经提供了 elasticsearchTemplate bean
}

  操作示例:

    由于 ElasticsearchTemplate 和 ElasticsearchRestTemplate 都实现了 ElasticsearchOperations 接口,因此使用它们的代码没有什么不同。该示例展示了如何在 Spring REST controller中使用注入的 ElasticsearchOperations 实例。

    根据我们的配置决定使用TransportClient 或 RestClient 

@RestController
@RequestMapping("es")
public class EsSearchController {

    private ElasticsearchOperations elasticsearchOperations;

    // 构造器注入ElasticsearchOperations bean
    public EsSearchController(ElasticsearchOperations elasticsearchOperations) {
        this.elasticsearchOperations = elasticsearchOperations;
    }

    /**
     * 在 Elasticsearch 集群中存储一些实体
     * @param person
     * @return
     */
    @PostMapping("/person")
    public String save(@RequestBody Person person) {
        IndexQuery indexQuery = new IndexQueryBuilder()
                .withId(person.getId().toString())
                .withObject(person)
                .build();
        String documentId = elasticsearchOperations.index(indexQuery);
        return documentId;
    }

    /**
     * 通过 id 检索具有查询的实体
     * @param id
     * @return
     */
    @GetMapping("/person/{id}")
    public Person findById(@PathVariable("id")  Long id) {
        Person person = elasticsearchOperations
                .queryForObject(GetQuery.getById(id.toString()), Person.class);
        return person;
    }
}

END.