SpringCloud学习笔记(十)Elasticsearch基础4-Java API Client

10.4 Java API Client操作-索引库/文档

客户端更新

ES为不同语言提供了用于操作ES的客户端,截至2023年7月4日,根据官网Java REST Client已经被弃用,取而代之的是Java API Client,黑马的教程里都是环境是es7.12.1`RestClient,版本太旧了,我的笔记用es 8.8.1Java API Client,但也会提供部分旧版本代码。ES官网也提供了兼容性支持,restclient7.17版本仍然可以操作es8.x版本。

API Client更新说明

image-20230704164100865
image-20230704164642426

为什么要抛弃High Level Rest:

  • 客户端”too heavy”,相关依赖超过 30 MB,且很多都是非必要相关的;api 暴露了很多服务器内部接口
  • 一致性差,仍需要大量的维护工作。
  • 客户端没有集成 json/object 类型映射,仍需要自己借助字节缓存区实现。

Java API Client最明显的特征:

  • 支持lambda表达式操作ES
  • 支持Builder建造者模式操作ES,链式代码具有较强可读性.
  • 应用程序类能够自动映射为Mapping.

可以浅浅感受下两者不同:

RestHighLevelClient:

image-20230705162855862
image-20230705163335206

导入本地项目

1.服务器mysql容器导入数据

 # 本地sql文件上传到服务器
 scp D:\...\tb_hotel.sql root@my_ip:/root/tmp
 # 复制文件到容器内
 docker cp tmp/tb_hotel.sql mysql:/tmp/tb_hotel.sql
 # 进入容器
 docker exec -it mysql bash
 mysql -u root -p
 # 容器内执行sql
 use my_db;
 source /tmp/tb_hotel.sql
 # 删除临时文件
 docker exec -it mysql rm /tmp/tb_hotel.sql

2.导入hotel-demo

数据结构分析

  • 需要分词:type=text,并设置分词器
  • 不需要索引:index=false
  • 特殊数据类型:geo_point表示具体经纬度,geo_shape表示经纬范围,如1所示
  • 优化搜索,如2所示⭐
    • 多条件索引的效率低于单条件索引
    • “copy_to”属性可将当前字段copy到指定字段
    • 创建条件”all”,将多条件索引的条件都”copy_to”新条件”all”,达成单条件索引
image-20230704162905494

初始化JavaClient

1.导入es的Client依赖,这里要注意jackson-core版本,原因看这篇

 <!--旧版本HLRC依赖-->
 <dependency>
     <groupId>org.elasticsearch.client</groupId>
     <artifactId>elasticsearch-rest-high-level-client</artifactId>
     <!--es7.17可以操作es8.x-->
     <version>7.17.4</version>
 </dependency>
 ​
 <!--新版本Java API Client依赖-->
  <dependency>
      <groupId>co.elastic.clients</groupId>
      <artifactId>elasticsearch-java</artifactId>
      <version>8.8.1</version>
 </dependency>
 ​
 ​
 <!--java api client需要有json对象映射库,springboot-web自带jackson-databind依赖,可以不引入-->
 <!--
 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-databind</artifactId>
     <version>2.12.7.1</version>
     <exclusions>
         <exclusion>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-core</artifactId>
         </exclusion>
     </exclusions>
 </dependency>
 -->
 <dependency>
     <groupId>com.fasterxml.jackson.core</groupId>
     <artifactId>jackson-core</artifactId>
     <version>2.12.0</version>
 </dependency>
 <!--如果报错找不到jakarta还需要引入如下依赖-->
 <dependency>
      <groupId>jakarta.json</groupId>
      <artifactId>jakarta.json-api</artifactId>
      <version>2.0.1</version>
 </dependency>

2.覆盖ES默认版本(Spring Boot默认ES版本7.6.2)

 <properties>
     <java.version>1.8</java.version>
     <elasticsearch.version>8.8.1</elasticsearch.version>
 </properties>

3.初始化Client

 //旧版本RestHighLevelClient
 @Bean
 public RestHighLevelClient restHighLevelClient(){
     return new RestHighLevelClient(RestClient.builder(
         HttpHost.create("http://xx.xx.xx.xx:9200")
    ));
 }
 //新版本Java API Client
 //新版版还支持创建安全连接,使用SSLContext
 @Bean
 public ElasticsearchClient elasticsearchClient(){
     //创建低级客户端,负责所有传输级问题:连接池、重试、节点发现等
     RestClient restClient = RestClient.builder(
         new HttpHost(IP,9200)).build();
     //使用Jackson映射器创建传输层,方便ES与应用程序类集成
     ElasticsearchTransport transport = new RestClientTransport(
         restClient,new JacksonJsonpMapper());
     //创建API 客户端
     //阻塞
     return new ElasticsearchClient(transport);
     //异步非阻塞
     //return new ElasticsearchAsyncClient(transport);
 }

索引库

创建索引测试

 @SpringBootTest
 class HotelIndexTest {
 ​
     // private RestHighLevelClient client;
 ​
     private RestClient restClient;
     private ElasticsearchTransport transport;
     private ElasticsearchClient client;
     
     @Test
     void testCreateIndex() throws IOException {
         //准备Request,并指定index name和请求参数
         CreateIndexRequest request = CreateIndexRequest.of(builder ->
             builder.index("hotel")
                    .withJson(new StringReader(MAPPING_TEMPLATE))
        );
         //发送请求
         client.indices().create(request);
    }
     
     
     //官方还提供了其他方法创建mappings
     //mappings是字符串
     @Test
     void testCreateIndex1() throws IOException {
         JsonpMapper jsonpMapper = client._transport().jsonpMapper();
         //这里的MAPPING_TEST字符串只需要包含{"properties":{}}内容
         JsonParser parser = Json.createParser(new StringReader(MAPPING_TEST));
         client.indices().create(
                 new CreateIndexRequest.Builder()
                        .index("hotel")
                      .mappings(TypeMapping._DESERIALIZER.deserialize(parser,jsonpMapper))
                        .build()
        );
    }
     //mappings是json文件
     @Test
     public void testCreateIndex2(){
         String mappingPath = System.getProperty("user.dir") + "/mappings.json";
         JsonpMapper mapper = client._transport().jsonpMapper();
         String mappings_str = new String(Files.readAllBytes(Paths.get(mappingPath)));
         System.out.println("mappings are: " +  mappings_str);
         JsonParser parser = mapper.jsonProvider()
            .createParser(new StringReader( mappings_str ));
 ​
         client.indices()
            .create(createIndexRequest -> createIndexRequest.index("test")
                    .mappings(TypeMapping._DESERIALIZER.deserialize(parser, mapper)));
    }
     
     @BeforeEach
     void setUp() {
         restClient = RestClient.builder(new HttpHost(IP,9200)).build();
         transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
         client = new ElasticsearchClient(transport);
    }
 ​
     @AfterEach
     void tearDown() throws IOException {
         //关闭连接
         restClient.close();
         transport.close();
    }
 }

API Client使用client.indices()操作索引.

image-20230705113225206

判断索引是否存在

 @Test
 void testExistsIndex() throws IOException {
     BooleanResponse isExists = client.indices().exists(
         new ExistsRequest.Builder()
         .index("hotel")
         .build()
     );
     System.out.println(isExists.value()?"exist":"not exist");
 }

其实代码是什么不重要,完全可以按提示写,例如删除index:

image-20230705154144666

提供了两种方式,上面判断是否存在用的是第二种,也就是XXIndexRequest的方式,删除可以试下第一种:

image-20230705154323920

改写成lambda表达式:

image-20230705154355621

文档

API Client使用client.xx()操作文档.

了解规则之后,根据代码提示直接写,不需要手动转换格式,极度舒适~

image-20230705164204097
image-20230705171150250
image-20230705171411436

bulk批量请求⭐

这个有点难猜,卡了一下

实在不行可以使用最原始的withJson()方法,把批量数据放在json中读取后作为请求参数传上去.但是不够优雅..

image-20230705174157104

2 thoughts on “SpringCloud学习笔记(十)Elasticsearch基础4-Java API Client

  1. MAPPING_TEST 这东西是哪里来的,源码中的还是?如何定义它的内容呢

    1. 这是Elastic Search的内容,创建一个es索引的时候可以定义它的mappings,是一个字符串。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注