SpringCloud系列(十五)[分布式搜索引擎篇] - 结合实际应用场景学习并使用 RestClient 客户端 API

16 篇文章 0 订阅
16 篇文章 0 订阅

前面的文章具体介绍了是索引库及文档的一些基本操作指令, 指令还是挺简单的; 那么实际应用场景下, 我们是如何操作 ElasticSearch 的呢?
 其实 ElasticSearch 官方已经为我们提供了各种不同语言的客户端, 目的就是为了来操作 ElasticSearch, 这些客户端的本质就是组装 DSL 语句, 通过 http 请求发送给 ElasticSearch, ➽官方文档地址.
在这里插入图片描述

❶ RestClient 的初始化操作

本文数据将借用某站的酒店数据库数据, 主要学习 RestClient 的含义及如何使用.

1.1 Mapping 映射分析

  关于索引库前面的博客已经说过最关键的是 mapping 映射, 因为 mapping 里面就是索引库的结构, 字段及子字段都在 properties 中, 主要注意下面几点:

  • 字段名和字段数据类型可以参照数据库表中的表结构名称和类型;
  • 根据业务来分析是否要参与搜索, 如图片地址就不需要参与搜索;
  • 根据内容来判断是否需要分词, 如果内容就是一个整体则无需分词;
  • 分词器根据业务来选择 ik_max_word 或者 ik_smart.

1.2 初始化 RestClient

  关于 RestClient 的初始化主要分为三步, 首先要做的是对 RestHighLevelClient 类的初始化, 建立与 ElasticSearch 的连接 (因为与 ElasticSearch 的一切交互都封装到了这个类中).

⅓: 引入 RestHighLevelClient 依赖

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

⅔: 检查自己的 SpringBoot 默认的 ElasticSearch 版本是哪个, 如果不是 7.17.7, 就要改成 7.17.7
在这里插入图片描述
1: 初始化 RestHighLevelClient

@Bean
    public RestHighLevelClient client() {
        return new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://172.16.**.**:9200")
        ));
    }

1.3 创建索引库

针对索引库的操作在测试类中使用; 关于索引库的创建也是分为三步:
Ⅰ: 创建 Request 对象, CreateIndexRequest create = new CreateIndexRequest(“hotel”);
Ⅱ: 添加请求参数, 这里的参数就是 DSL 中 JSON 参数部分, 因为字符串比较长, 可以定义一个静态字符串常量;
Ⅲ: 发送请求, client.indices() 方法的返回值是 IndicesClient 类型, 封装了所有与索引库操作有关的方法.

@Test
    void createHotelIndex() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        client.indices().create(request, RequestOptions.DEFAULT);
    }
// 静态字符串常量 MAPPING_TEMPLATE
public static final String MAPPING_TEMPLATE = "{\n" +
            "  \"mappings\": {\n" +
            "    \"properties\": {\n" +
            "      \"id\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"name\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\"\n" +
            "      },\n" +
            "      \"address\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"price\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"score\": {\n" +
            "        \"type\": \"integer\"\n" +
            "      },\n" +
            "      \"brand\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"city\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"starName\": {\n" +
            "        \"type\": \"keyword\"\n" +
            "      },\n" +
            "      \"business\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"copy_to\": \"all\"\n" +
            "      },\n" +
            "      \"location\": {\n" +
            "        \"type\": \"geo_point\"\n" +
            "      },\n" +
            "      \"pic\": {\n" +
            "        \"type\": \"keyword\",\n" +
            "        \"index\": false\n" +
            "      },\n" +
            "      \"all\": {\n" +
            "        \"type\": \"text\",\n" +
            "        \"analyzer\": \"ik_max_word\"\n" +
            "      }\n" +
            "    }\n" +
            "  }\n" +
            "}";
}

在这里插入图片描述


1.4 删除索引库

  上篇博客可以看的出来删除索引库的 DSL 语句比较简单, DELETE /索引库名, 与 创建索引库相比只不过是由 PUT 变成了 DELETE, 请求路径无需改变, 也没有任何请求参数. 当然代码还是分三步走:
Ⅰ: 创建 Request 对象, 注意这次不再是 CreateIndexRequest create 对象, 而是 DeleteIndexRequest 对象;
Ⅱ: 准备参数, 当然这里无参数;
Ⅲ: 发送请求, 改成了 delete 方法; client.indices() 方法的返回值是 IndicesClient 类型, 封装了所有与索引库操作有关的方法.

@Test
    void testDeleteHotelIndex() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
        client.indices().delete(request, RequestOptions.DEFAULT);
    }


1.5 查询索引库 (判断索引库是否存在)

查询索引库操作对应的 DSL 语句是 GET /索引库名 ;
Ⅰ: 创建 Request 对象, 这次是 GetIndexRequest 对象;
Ⅱ: 准备参数, 当然这里也是无参数;
Ⅲ: 发送请求, 改成了 exists 方法; client.indices() 方法的返回值是 IndicesClient 类型, 封装了所有与索引库操作有关的方法.

@Test
    void testExistsHotelIndex() throws IOException {
        GetIndexRequest request = new GetIndexRequest("hotel");
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
    }

在这里插入图片描述

1.6 总结

通过上面的创建 / 删除 / 查询 操作可以看得出来, JavaRestClient 的步骤和 ElasticSearch 的流程基本相似, 核心都在 client.indices() 这个方法上, 索引库的基本步骤如下:

  • 初始化 RestHighLevelClient;
  • 创建各自的 Request;
  • 准备 DSL, 只有创建的时候需要用到, 查询删除都用不到;
  • 发送请求, 调用 client.indices() 这个方法.

❷ RestClient 文档操作

关于 RestClient 文档的操作也是要参照已经写好的 DSL 语句, 操作并不是很难; 但是前提是要确定好自己的数据库的实体类, 其次还要定义一个新的实体类, 这个实体类要与索引库的结构吻合 (我这里的数据还是用的某站酒店的数据).

2.1 新增文档

关于文档的新增也是分为三步走, 先是创建 Request 对象, 然后准备请求的参数, 也就是 DSL 中的数据, 最后发送请求即可.

@Test
    void testAddDocument() throws IOException {
        Hotel hotel = hotelService.getById(1);
        HotelDoc hotelDoc = new HotelDoc(hotel);

        IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
        request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
        client.index(request, RequestOptions.DEFAULT);
    }

在这里插入图片描述

我们从数据库中获取到的数据需要先查询出来, 得到数据对象, 然后需要转换为 HotelDoc 对象 (因为要与索引库的结构一致), 然后再序列化为 json 格式;

具体流程步骤:

  • 根据 id 查询到产品数据;
  • 将查询到的数据对象封装成 Doc 类型 (要与索引库的结构一致);
  • 将 Doc 数据序列化为 JSON 格式;
  • 创建 IndexRequest ,指定索引库的名称及 id;
  • 准备请求参数, 也就是刚才已经转换的 JSON 文档;
  • 发送请求, 注意这里不再是 client.indeces()了.

2.2 查询文档

查询文档比较简单, 只需要准备 Request 对象, 然后发送请求即可; 这里还是要注意, 查询到的是 JSON 文档, 因此需要将 JSON 数据进行解析.

@Test
    void testGetDocumentById() throws IOException {
        GetRequest request = new GetRequest("hotel","61083");
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        String json = response.getSourceAsString();

        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        System.out.println(hotelDoc);
    }

在这里插入图片描述

具体步骤:

  • 准备 GetRequest 对象;
  • 发送请求, client.get() 进行请求, 得到的是 json 格式;
  • 解析结果, 也就是将 json 文档进行反序列化.

2.3 删除文档

删除文档和查询文档基本类似, 只是将 get 改成了 delete;

@Test
    void testDeleteDocument() throws IOException {
        DeleteRequest request = new DeleteRequest("hotel", "1");
        client.delete(request, RequestOptions.DEFAULT);
    }

在这里插入图片描述
具体步骤:

  • 准备 DeleteRequest 对象, 指定索引库的名字及 id;
  • 发送请求, 使用 client.delete() 方法.

2.4 修改文档

关于文档的修改前面的文章已经说过有两种方法, 全量修改和增量修改;

  • 全量修改: 本质是先根据 id 删除, 然后再新增;
  • 增量修改: 就是直接修改文档中指定的字段值;
  • 当然在 RestClient 的 API 中, 是根据 id 是否存在来进行判断, 如果存在就修改, 不存在就新增.
@Test
    void testUpdateDocument() throws IOException {
        UpdateRequest request = new UpdateRequest("hotel", "1");
        request.doc(
                "name", "Remake",
                "age", "999"
        );
        client.update(request, RequestOptions.DEFAULT);
    }

在这里插入图片描述
具体步骤:

  • 准备 Request 对象, 修改用的是 UpdateRequest;
  • 准备参数, 也就是 JSON 文档, 里面包含了所要修改的字段;
  • 更新文档, 调用 client.update() 方法.

❸ 批量数据导入

批量数据的导入用到了 BulkRequest, 具体步骤和新增基本一致, 先查询到数据库中的数据, 然后转换为 Doc 文档数据, 利用 BulkRequest 进行批处理, 实现批量数据的新增文档.
批量数据的新增其实质就是将多个 CRUD 请求组合在一起进行发送, 其中提供了一个 add 方法, 用来添加其他的请求, 其他的请求就包含了新增, 修改和删除操作.

@Test
    void testBulkRequest() throws IOException {
        List<Hotel> hotels = hotelService.list();
        
        BulkRequest request = new BulkRequest();
        for (Hotel hotel : hotels) {
            HotelDoc hotelDoc = new HotelDoc(hotel);
            request.add(new IndexRequest("hotel")
                    .id(hotelDoc.getId().toString())
                    .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
        }
        client.bulk(request, RequestOptions.DEFAULT);
    }

具体步骤:

  • 从数据库中查到批量数据;
  • 创建 Request 请求, 用到了 BulkRequest;
  • 准备参数, 添加多个新增的 Request, 这里也要转换为 Doc 文档 (要与索引库的结构一致) 格式;
  • 发送请求.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值