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依赖:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
            <version>2.6.2</version>
        </dependency>

 

 

一、客户端

  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<IndexResponse> 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<Header> 函数,每次在请求发送到 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对象映射是将一个Java对象(域实体)映射为存储在Elasticsearch中的JSON文档

  映射注释:

    @Document:在实体类上使用,用来指示该类是映射到数据库候选对象,有如下属性:

      indexName:存储此实体的索引的名称。

      createIndex:标记是否创建索引,默认为true

      versionType:版本管理的配置,默认为EXTERNAL

    @Id:用来将对象中id和ES中_id映射

    @Transient:默认情况下,所有字段在存储或检索时都映射到文档,此注释不包括该字段

    @PersistenceConstructor:标记一个给定的构造函数,可以是一个包保护的构造函数。在从数据库实例化对象时使用,构造函数按名称映射到检索到的Document中的键值

    @Field:应用于字段级别并定义字段的属性,此注解有如下属性:

      name:Elasticsearch 文档中表示的字段名称,如果未设置,则使用 Java 字段名称

      type:字段类型,可以是Text、Keyword、Long、Integer、Short、Byte、Double、Float、Half_Float、Scaled_Float、Date、Date_Nanos、Boolean、Binary、Integer_Range、Float_Range、Long_Range、Double_Range、Date_Range、Ip_Range、Object 之一, 嵌套, Ip, TokenCount, Percolator, Flattened, Search_As_You_Type。

        如果未指定字段类型,则默认为FieldType.Auto,这意味着,不会为该属性不会为该属性写入任何映射条目,并且 Elasticsearch 将在存储该属性的第一个数据时动态添加一个映射条目

      format:一种或多种内置日期格式 日期格式映射

      pattern:一种或多种自定义日期格式 日期格式映射

      store:标记原始字段值是否应该存储在 Elasticsearch 中,默认值为false

      analyer、searchAnalyzer、normalizer:用于指定自定义分析器和规范器

 

    日期格式映射:

annotation format string in Elasticsearch mapping

@Field(type=FieldType.Date)

"date_optional_time||epoch_millis",

@Field(type=FieldType.Date, format=DateFormat.basic_date)

"basic_date"

@Field(type=FieldType.Date, format={DateFormat.basic_date, DateFormat.basic_time})

"basic_date||basic_time"

@Field(type=FieldType.Date, pattern="dd.MM.uuuu")

"date_optional_time||epoch_millis||dd.MM.uuuu",

@Field(type=FieldType.Date, format={}, pattern="dd.MM.uuuu")

"dd.MM.uuuu"

  

 

 

 

四、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 

import com.yang.custom.es.model.Employee;
import org.elasticsearch.index.query.QueryBuilders;
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.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

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

    /**
     * ElasticsearchTemplate 和 ElasticsearchRestTemplate 都实现了 ElasticsearchOperations 接口
     * Spring根据配置注入ElasticsearchTemplate或ElasticsearchRestTemplate
     */
    private ElasticsearchOperations elasticsearchOperations;

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

    /**
     * 根据条件查询文档数据
     *
     * @return
     */
    @GetMapping("query")
    public List<Employee> queryEmployees() {
        // 构造查询条件,查询索引中last_name属性值为Smith的文档
        NativeSearchQuery nativeQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("last_name", "Smith"))
                .build();
        // 查询
        SearchHits<Employee> searchHits = elasticsearchOperations.search(nativeQuery, Employee.class);
        List<SearchHit<Employee>> searchHitList = searchHits.getSearchHits();
        List<Employee> employees = new ArrayList<>();
        for (SearchHit<Employee> searchHit : searchHitList) {
            Employee employee = searchHit.getContent();
            employees.add(employee);
        }
        return employees;
    }

    /**
     * 插入文档到索引
     */
    @PutMapping
    public void insertEmployee() {
        Employee employee = new Employee();
        employee.setFirstName("yang");
        employee.setLastName("yongjie");
        employee.setAge(26);
        employee.setAbout("badminton");
        elasticsearchOperations.save(employee);
    }
}

    Employee实体:

import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.util.List;

@Document(indexName = "megacorp")
public class Employee {
    @Field(name = "first_name", type = FieldType.Text)
    private String firstName;
    @Field(name = "last_name", type = FieldType.Text)
    private String lastName;
    @Field(type = FieldType.Integer)
    private Integer age;
    @Field(type = FieldType.Text)
    private String about;
    private List<String> interests;
    // getter and setter ...
}

 

  Bulk操作

    批量请求允许在一个请求中向 Elasticsearch 发送多个与文档相关的操作。当您有多个文档要摄取时,这比使用单独的请求发送每个文档更有效

    Bulk请求可以包含以下几种操作:

      create:创建一个文档,在确保它不存在后对其进行索引

      index:索引文档,在需要时创建它,如果存在则替换它(注意:替换不是更新)

      update:更新一个已经存在的文档,可以是一个脚本,也可以是一个部分文档

      delete:删除一个文档

        // BulkRequest 建造器
        BulkRequest.Builder br = new BulkRequest.Builder();
        br.operations(op -> op
                .index(idx -> idx
                        .index("products")
                        .id(product.getSku())
                        .document(product)
                )
        );
        br.operations(new BulkOperation.Builder().create().build());
        br.operations(new BulkOperation.Builder().index().build());
        br.operations(new BulkOperation.Builder().update().build());
        br.operations(new BulkOperation.Builder().delete().build());
        // 
        BulkResponse result = elasticsearchClient.bulk(br.build());

 

RESTful示例:

curl -X POST "localhost:9200/_bulk?pretty" -H 'Content-Type: application/json' -d'
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }
'

Python:

resp = client.bulk(
    body=[
        {"index": {"_index": "test", "_id": "1"}},
        {"field1": "value1"},
        {"delete": {"_index": "test", "_id": "2"}},
        {"create": {"_index": "test", "_id": "3"}},
        {"field1": "value3"},
        {"update": {"_id": "1", "_index": "test"}},
        {"doc": {"field2": "value2"}},
    ],
)
print(resp)

  注意:update json数据前要加 doc

Bulk文档:https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/indexing-bulk.html

 

 

以上为Spring集成的Elasticsearch客户端的使用,下面是原生的Java API Client

 

五、Elasticsearch Java API Client

  1、依赖

<dependencies>

    <dependency>
      <groupId>co.elastic.clients</groupId>
      <artifactId>elasticsearch-java</artifactId>
      <version>8.1.2</version>
    </dependency>

  <!-- spring框架会依赖,不必添加 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.12.3</version> </dependency> </dependencies>

  依据官方文档,如果出现了 ClassNotFoundException: jakarta.json.spi.JsonProvider 异常,则添加以下依赖:

     <!-- Needed only if you use the spring-boot Maven plugin -->
    <dependency> 
      <groupId>jakarta.json</groupId>
      <artifactId>jakarta.json-api</artifactId>
      <version>2.0.1</version>
    </dependency> 

  注意:在多模块项目中,如果在common模块中添加此依赖,仍会报上面异常。将elasticsearch-java依赖在common模块中配置,将jakarta.json-api在顶级启动模块中配置即可。

 

 

  2、连接

  Java API 客户端围绕三个主要组件构建:

    ①:API 客户端类。它们为 Elasticsearch API 提供强类型数据结构和方法。由于 Elasticsearch API 很大,它以功能组(也称为“命名空间”)的形式进行结构化,每个功能组都有自己的客户端类。Elasticsearch 核心功能在ElasticsearchClient类中实现。
    ②:JSON 对象映射器。这会将您的应用程序类映射到 JSON 并将它们与 API 客户端无缝集成。
    ③:传输层实现。这是所有 HTTP 请求处理发生的地方

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * es客户端配置
 *
 * @author yangyongjie
 * @date 2022/10/17
 */
@Configuration
public class EsRestClientConfig {

    @Bean
    public ElasticsearchClient esClient() {
        // 身份认证
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("user", "test-user-password"));
        // 创建低级客户端
        RestClient restClient = RestClient.builder(
                new HttpHost("localhost", 9200))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                        return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                })

                .build();
        //使用 Jackson 映射器创建传输
        ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        // 创建低级客户端
        ElasticsearchClient client = new ElasticsearchClient(transport);
        return client;
    }

}

  

  3、索引操作

    ①:添加索引

        CreateIndexResponse response = elasticsearchClient.indices().create(new CreateIndexRequest.Builder()
                .index(appIndexName)
                .settings(new IndexSettings.Builder()
                        .numberOfShards("3") // 三个分片
                        .numberOfReplicas("1") // 每个分片一个副本
                        .build())
                .aliases("appstore_app_info", new Alias.Builder().
                        isWriteIndex(true)
                        .build())
                .build());
        String index = response.index();

    ②:删除索引

 DeleteIndexResponse deleteIndexResponse = elasticsearchClient.indices().delete(new DeleteIndexRequest.Builder()
                .index(appIndexName)
                .build());

 

 

  4、文档操作

    ①:搜索

        SearchResponse<AppInfo> response = elasticsearchClient.search(new SearchRequest.Builder()
                        .index(appIndexName)
                        .query(new Query.Builder()
                                // match_phrase搜索
                                .matchPhrase(new MatchPhraseQuery.Builder()
                                        .field("app_name.pinyin")
                                        .query("sc")
                                        .build())
                                // wildcard搜索
//                                .wildcard(new WildcardQuery.Builder()
//                                        .field("traceId")
//                                        .value("*htmn")
//                                        .build())
                                // match搜索
//                                .match(new MatchQuery.Builder()
//                                        .field("app_name")
//                                        .query("hello")
//                                        .build())
                                // term搜索
//                                .term(new TermQuery.Builder()
//                                        .field("app_name")
//                                        .value(new FieldValue.Builder().stringValue("视频头条").build())
//                                        .build())
                                .build())
                        // 分页
                        .from(10)
                        .size(10)
                        .build(),
                AppInfo.class);

    term搜索:

GET index_name/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "field1": "value1"
          }
        },
        {
          "term": {
            "field2": "value2"
          }
        }
      ]
    }
  }
}


        SearchResponse<Map> response = elasticsearchClient.search(new SearchRequest.Builder()
                        .index("index_name")
                        .query(new Query.Builder()
                                .bool(new BoolQuery.Builder()
                                        .must(new Query.Builder()
                                                        // term搜索
                                                        .term(new TermQuery.Builder()
                                                                .field("field1")
                                                                .value(new FieldValue.Builder().stringValue("value1").build())
                                                                .build())
                                                        .build(),
                                                new Query.Builder()
                                                        // term搜索
                                                        .term(new TermQuery.Builder()
                                                                .field("field2")
                                                                .value(new FieldValue.Builder().stringValue("value2").build())
                                                                .build())
                                                        .build()
                                        )
                                        .build())
                                .build())
                        .build(),
                Map.class);

    terms搜索:

        List<FieldValue> fieldValues=new ArrayList<>();
        fieldValues.add(new FieldValue.Builder().stringValue("视频头条").build());
        fieldValues.add(new FieldValue.Builder().stringValue("电视商城").build());
        // 索引
        searchRequestBuilder.index(indexName)
                .query(new Query.Builder()
                        .terms(new TermsQuery.Builder()
                                .field("app_name")
                                .terms(new TermsQueryField.Builder().value(fieldValues).build())
                                .build())
                        .build())
                // 分页
                .from(traceLogQuery.getFrom())
                .size(traceLogQuery.getSize());

    ②:写文档

        long id = 12L;
        AppInfo appInfo = new AppInfo();
        appInfo.setId(id);
        appInfo.setAppName("电视商店");
        appInfo.setUpdateTime(new Date());
        CreateResponse createResponse = esClient.create(new CreateRequest.Builder<AppInfo>()
                .id(String.valueOf(id)) // 对应_id,建议设设置值与doc中的id值一致
                .index("mib_tv_appstore_app_info")
                .document(appInfo)
                .build());

    ③:更新

     AppInfo appInfo = new AppInfo();
        appInfo.setApp_name("电视商城");
        appInfo.setIs_default_recommend(CommonConstant.STR_ONE);
        appInfo.setIs_online(CommonConstant.STR_ONE);

        UpdateResponse<AppInfo> updateResponse = elasticsearchClient.update(new UpdateRequest.Builder<AppInfo, AppInfo>()
                .index(appIndexName)
                .id("1")
                .doc(appInfo)
                .docAsUpsert(true) // 如果文档不存在,则插入新文档
                .build(), AppInfo.class);

    ④:删除

        /*// 查询并删除
        elasticsearchClient.deleteByQuery(new DeleteByQueryRequest.Builder()
                .index(appIndexName)
                .query(new Query.Builder()
                        .match(new MatchQuery.Builder()
                                .field("app_name")
                                .query("hello elasticsearch")
                                .build())
                        .build())
                .build());*/
        // 根据id删除
        DeleteResponse deleteResponse = elasticsearchClient.delete(new DeleteRequest.Builder()
                .index(appIndexName)
                .id("1")
                .build());

     ⑤:根据id获取文档

        GetResponse<AppInfo> getResponse = elasticsearchClient.get(new GetRequest.Builder()
                        .index(appIndexName)
                        .id(String.valueOf(id))
                        .build(),
                AppInfo.class);
        // 是否找到,即id的文档是否存在
        boolean found = getResponse.found();
        AppInfo appInfo = getResponse.source();

    ⑥:upset,存在更新,不存在插入

UpdateRequest updateRequest=new UpdateRequest.Builder<Map, Map>()
                .index(index)
                .id(oneId)
                .doc(mediaMap)
                .docAsUpsert(true) //不存在则插入
                .build();
        
        // 更新es
        elasticsearchClient.update(updateRequest, Map.class);

 

  

HTTP方式:

  1、依赖

        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>7.17.9</version>
        </dependency>

  2、配置RestHighLevelClient

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Elasticsearch 配置类
 */
@Configuration
public class ElasticSearchConfig {

    @Value("${es.knowledge.url}")
    private String serverUri;
    @Value("${es.knowledge.username}")
    private String knowledgeUserName;
    @Value("${es.knowledge.access1}")
    private String knowledgePassword;

    @Bean(destroyMethod = "close")
    public RestHighLevelClient esRestHighLevelClient() {
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(knowledgeUserName, knowledgePassword));
        RestHighLevelClient restHighLevelClient = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost(HttpHost.create(serverUri))
                ).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                        httpClientBuilder.disableAuthCaching();
                        return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                })
        );
        return restHighLevelClient;
    }

}

  3、操作

    @Resource(name = "esRestHighLevelClient")
    private RestHighLevelClient esRestHighLevelClient;

    @Test
    void restHighLevelClientTest() throws IOException {
        SearchRequest searchRequest = new SearchRequest();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.termsQuery("metaId", "103249"));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = esRestHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits searchHits=searchResponse.getHits();
    }

  

 

 

Jest客户端

  Jest是一个ElasticSearch Java HTTP Rest 客户端(18年之后不再维护,对新版es不能支持)

  1、添加依赖

        <dependency>
            <groupId>io.searchbox</groupId>
            <artifactId>jest</artifactId>
            <version>6.3.1</version>
        </dependency>

  2、创建JestClient实例

   注意:JavaClient 设计为单例的,不必为每个请求都创建

import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.config.HttpClientConfig;
import org.springframework.context.annotation.Configuration;

/**
 * Elasticsearch Jest客户端
 *
 * @author yangyongjie
 */
@Configuration
public class ElasticSearchJestConfig {

    @Bean
    public JestClient jestClient() {
        // 根据JestClientFactory创建一个Jest客户端
        JestClientFactory factory = new JestClientFactory();
        factory.setHttpClientConfig(new HttpClientConfig
                .Builder("http://localhost:9200")
                .defaultCredentials("username", "password")
                .multiThreaded(true)
                // 每个路由绑定最大连接数,默认不超过2个
                .defaultMaxTotalConnectionPerRoute(2)
                // 最大连接数
                .maxTotalConnection(20)
                .build());
        JestClient client = factory.getObject();
        return client;
    }
}

  3、操作示例

    @Resource
    private JestClient jestClient;

    @Test
    public void jestClientTest() throws IOException {
        String query = "{\n" +
                "  \"query\": {\n" +
                "    \"term\": {\n" +
                "      \"metaId\": {\n" +
                "        \"value\": \"103249\"\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}";
        Search search = new Search.Builder(query)
                // multiple index or types can be added.
                .addIndex("tv_knowledge_movie_update_calendar_staging")
                .build();

        SearchResult result = jestClient.execute(search);
        System.out.println(result);
    }

 

 

 

附录:

  ES客户端文档:https://www.elastic.co/guide/en/elasticsearch/client/index.html 

  Jest客户端:https://github.com/searchbox-io/Jest/blob/master/jest/README.md#comparison-to-native-api

 

END.

posted @ 2022-01-09 22:38  杨岂  阅读(2061)  评论(0编辑  收藏  举报