RestClient操作 Elasticsearch(ES)索引库和文档

RestClient操作 Elasticsearch(ES)索引库和文档

今日目标

  • 掌握RestClient操作索引和文档

什么是RestClient

ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html

RestClient操作 Elasticsearch(ES)索引库和文档

其中的Java Rest Client又包括两种:

  • Java Low Level Rest Client
  • Java High Level Rest Client 我们学习的是Java HighLevel Rest Client客户端API

1.  RestClient操作索引库项目准备

1.1. 项目准备

首先导入数据库数据elastic

数据结构如下


create database elastic;
use elastic;

SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for tb_wine_shop
-- ----------------------------
DROP TABLE IF EXISTS `tb_wine_shop`;
CREATE TABLE `tb_wine_shop`  (
                                 `id` bigint(20NOT NULL COMMENT '酒店id',
                                 `name` varchar(255CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店名称',
                                 `address` varchar(255CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店地址',
                                 `price` int(10NOT NULL COMMENT '酒店价格',
                                 `score` int(2NOT NULL COMMENT '酒店评分',
                                 `brand` varchar(32CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店品牌',
                                 `city` varchar(32CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所在城市',
                                 `star_name` varchar(16CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '酒店星级,1星到5星,1钻到5钻',
                                 `business` varchar(255CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商圈',
                                 `latitude` varchar(32CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '纬度',
                                 `longitude` varchar(32CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '经度',
                                 `pic` varchar(255CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '酒店图片',
                                 PRIMARY KEY (`id`USING BTREE
ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

1.2. 导入elastic-demo项目

项目地址:https://github.com/bangbangzhou/learn_springboot/tree/main/elastic-demo

项目结构如图:

RestClient操作 Elasticsearch(ES)索引库和文档

1.3. mapping映射分析

如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

原创不易,转载请注明出处,感谢支持!如果本文对您有用,欢迎转发分享!


创建索引库,最关键的是mapping映射,而mapping映射要考虑的信息包括:

  • 字段名
  • 字段数据类型
  • 是否参与搜索
  • 是否需要分词
  • 如果分词,分词器是什么? 其中:
  • 字段名、字段数据类型,可以参考数据表结构的名称和类型
  • 是否参与搜索要分析业务来判断,例如图片地址,就无需参与搜索
  • 是否分词呢要看内容,内容如果是一个整体就无需分词,反之则要分词
  • 分词器,我们可以统一使用ik_max_word 来看下wineshop的索引库结构:

PUT /wineshop
{
  "mappings": {
    "properties": {
      "id": {
        "type""keyword"
      },
      "name":{
        "type""text",
        "analyzer""ik_max_word",
        "copy_to""all"
      },
      "address":{
        "type""keyword",
        "index"false
      },
      "price":{
        "type""integer"
      },
      "score":{
        "type""integer"
      },
      "brand":{
        "type""keyword",
        "copy_to""all"
      },
      "city":{
        "type""keyword",
        "copy_to""all"
      },
      "starName":{
        "type""keyword"
      },
      "business":{
        "type""keyword"
      },
      "location":{
        "type""geo_point"
      },
      "pic":{
        "type""keyword",
        "index"false
      },
      "all":{
        "type""text",
        "analyzer""ik_max_word"
      }
    }
  }
}

几个特殊字段说明

  • location:地理坐标,里面包含精度、纬度
  • all:一个组合字段,其目的是将多字段的值 利用copy_to合并,提供给用户搜索地理坐标说明ES中支持两种地理坐标数据类型
  • geo_point:由纬度(latitude)和经度(longitude)确定的一个点。例如:”32.8752345, 120.2981576″
  • geo_shape:有多个geo_point组成的复杂几何图形。例如一条直线,”LINESTRING (-77.03653 38.897676, -77.009051 38.889939)”

copy_to说明:字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段。示例:

"all": {
  "type""text",
  "analyzer""ik_max_word"
},
"brand": {
  "type""keyword",
  "copy_to""all"
}

1.4.初始化RestClient

【步骤一】:引入es的RestHighLevelClient依赖:

因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本:

<!--        elasticsearch-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.14.1</version>
    <exclusions>
        <exclusion>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.14.1</version>
</dependency>

【步骤二】:初始化RestHighLevelClient:

ES实例化RestHighLevelClient时指定用户名和密码

com.zbbmeta.elastic.config包下创建RestHighLevelClientConfig类进入注入RestHighLevelClient到Spring容器

@Configuration
public class RestHighLevelClientConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient(){
        // 配置用户名和密码
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic""123456"));
        // 创建 RestHighLevelClient
       return new RestHighLevelClient(
                RestClient.builder( HttpHost.create("http://192.168.150.102:9200"))
                        .setHttpClientConfigCallback(httpClientBuilder ->
                                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
        );

    }
}

2. RestHighLevelClien操作ES索引库

2.1. RestHighLevelClient创建ES索引库

创建WineShopIndexTest测试了,在测试类下创建索引库的代码如下:


/**
 * 创建wineshop索引库
 */

@Test
public void createHotelIndex() throws IOException {
    // 1.创建Request对象
    CreateIndexRequest request = new CreateIndexRequest("wineshop");
    // 2.准备请求的参数:DSL语句
    request.source(MAPPING_TEMPLATE, XContentType.JSON);
    // 3.发送请求
    client.indices().create(request, RequestOptions.DEFAULT);
}

代码解读

RestClient操作 Elasticsearch(ES)索引库和文档代码分为三步:

  • 1.创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。
  • 2.添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。
  • 3.发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索库操作有关的方法。

使用DSL语句在控制台查看

# 查询wineshop索引
GET /wineshop
RestClient操作 Elasticsearch(ES)索引库和文档

2.2. RestHighLevelClient删除ES索引库

删除索引库的DSL语句非常简单:

## 删除wineshop索引
DELETE /wineshop
RestClient操作 Elasticsearch(ES)索引库和文档

删除ES索引库与创建索引库相比

  • 请求方式从PUT变为DELTE
  • 请求路径不变
  • 无请求参数Java代码的差异,依然是三步走

    1. 创建Request对象。这次是DeleteIndexRequest对象

    1. 准备参数。这里是无参

    1. 发送请求。改用delete方法 在WineShopIndexTest测试类中,编写单元测试,实现删除索引:
/**
 * 
 *删除wineshop索引库
 */

@Test
void testDeleteWineShopIndex() throws IOException {
    // 1.创建Request对象
    DeleteIndexRequest request = new DeleteIndexRequest("wineshop");
    // 2.发送请求
    client.indices().delete(request, RequestOptions.DEFAULT);
}

2.3. RestHighLevelClient判断ES索引库是否存在

判断索引库是否存在,对应的DSL是:

## 判断wineshop索引是否存在
GET /wineshop

RestClient操作 Elasticsearch(ES)索引库和文档Java代码,依然是三步走


    1. 创建Request对象。这次是GetIndexRequest对象

    1. 准备参数。这里是无参

    1. 准备参数。这里是无参 在WineShopIndexTest测试类中,编写单元测试,实现判断ES索引库是否存在:

/**
 *
 * 判断ES索引库WineShop是否存在
 */

@Test
void testExistsWineShopIndex() throws IOException {
    // 1.创建Request对象
    GetIndexRequest request = new GetIndexRequest("wineshop");
    // 2.发送请求
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    // 3.输出
    System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}

结果:

RestClient操作 Elasticsearch(ES)索引库和文档

3.RestHighLevelClient操作文档

3.1. RestHighLevelClient新增ES文档

我们要将数据库的tb_wine_shop数据查询出来,写入elasticsearch中。

索引库WineShop实体类

com.zbbmeta.elastic.entity包下创建WineShop实体类

package com.zbbmeta.elastic.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

import java.io.Serializable;

/**
 * 
 * @TableName tb_wine_shop
 */

@TableName(value ="tb_wine_shop")
@Data
@ToString
@EqualsAndHashCode
public class WineShop implements Serializable {
    /**
     * 酒店id
     */

    @TableId(type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 酒店名称
     */

    private String name;

    /**
     * 酒店地址
     */

    private String address;

    /**
     * 酒店价格
     */

    private Integer price;

    /**
     * 酒店评分
     */

    private Integer score;

    /**
     * 酒店品牌
     */

    private String brand;

    /**
     * 所在城市
     */

    private String city;

    /**
     * 酒店星级,1星到5星,1钻到5钻
     */

    private String starName;

    /**
     * 商圈
     */

    private String business;

    /**
     * 纬度
     */

    private String latitude;

    /**
     * 经度
     */

    private String longitude;

    /**
     * 酒店图片
     */

    private String pic;

    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
   
}

与我们的索引库结构存在差异:

  • longitude和latitude需要合并为location 因此,我们需要定义一个新的类型,与索引库结构吻合WineShopDoc类:
package com.zbbmeta.elastic.entity;

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class WineShopDoc {
    private Long id;
    private String name;
    private String address;
    private Integer price;
    private Integer score;
    private String brand;
    private String city;
    private String starName;
    private String business;
    private String location;
    private String pic;

    public WineShopDoc(WineShop wineShop) {
        this.id = wineShop.getId();
        this.name = wineShop.getName();
        this.address = wineShop.getAddress();
        this.price = wineShop.getPrice();
        this.score = wineShop.getScore();
        this.brand = wineShop.getBrand();
        this.city = wineShop.getCity();
        this.starName = wineShop.getStarName();
        this.business = wineShop.getBusiness();
        this.location = wineShop.getLatitude() + ", " + wineShop.getLongitude();
        this.pic = wineShop.getPic();
    }
}

新增ES文档语法说明

·新增文档的DSL语句如下:

POST /{索引库名}/_doc/1
{
    "name""springboot葵花宝典",
    "age"21
}

Java代码,依然是三步走


    1. 创建Request对象

    1. 准备请求参数,也就是DSL中的JSON文档

    1. 发送请求变化的地方在于,这里直接使用client.xxx()的API,不再需要client.indices()了。WineShopIndexTest测试类中,编写单元测试,实现新增ES文档:
/**
 * 
 *新增WineShop下的文档数据
 */

@Test
void testAddWineShopDocument() throws IOException {
    // 1.根据id查询酒店数据
    WineShop wineShop = wineShopService.getById(61083L);
    // 2.转换为文档类型
    WineShopDoc wineShopDoc = new WineShopDoc(wineShop);
    // 3.将WineShopDoc转json
    String json = JSON.toJSONString(wineShopDoc);

    // 1.准备Request对象
    IndexRequest request = new IndexRequest("wineshop").id(wineShopDoc.getId().toString());
    // 2.准备Json文档
    request.source(json, XContentType.JSON);
    // 3.发送请求
    client.index(request, RequestOptions.DEFAULT);
}

结果:

RestClient操作 Elasticsearch(ES)索引库和文档

3.2. RestHighLevelClient查询ES文档

查询ES文档语法说明

查询DSL语句如下

GET /wineShop/_doc/{id}

java非常简单 分两步

  • 准备Request对象
  • 发送请求

不过查询的目的是得到结果,解析为WineShopDoc,因此难点是结果的解析。完整代码如下:

/**
 * 
 * 查询WineShop下的id=61083文档数据
 */

@Test
void testGetWineShopDocumentById() throws IOException {
    // 1.准备Request
    GetRequest request = new GetRequest("wineshop""61083");
    // 2.发送请求,得到响应
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    // 3.解析响应结果
    String json = response.getSourceAsString();

    WineShopDoc wineShopDoc = JSON.parseObject(json, WineShopDoc.class);
    System.out.println(wineShopDoc);
}

结果对比

RestClient操作 Elasticsearch(ES)索引库和文档

3.3  RestHighLevelClient删除ES文档

删除的DSL语句如下:

DELETE /wineshop/_doc/{id}

和DSL查询相比,仅仅是请求方式从DELETE变成GET,可以想象Java代码应该依然是三步走:


    1. 准备Request对象,因为是删除,这次是DeleteRequest对象。要指定索引库名和id

    1. 准备参数,无参

    1. 发送请求。因为是删除,所以是client.delete()方法

在WineShopIndexTest测试类中,编写单元测试:

/**
 * 删除WineShop下的id=61083文档数据
 */

@Test
void testDeleteWineShopDocument() throws IOException {
    // 1.准备Request
    DeleteRequest request = new DeleteRequest("wineshop""61083");
    // 2.发送请求
    client.delete(request, RequestOptions.DEFAULT);
}

3.4. RestHighLevelClient修改ES文档

修改文档两种方式:

  • 全量修改:本质是先根据id删除,再新增
  • 增量修改:修改文档中的指定字段值 在RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:
  • 如果新增时,ID已经存在,则修改
  • 如果新增时,ID不存在,则新增 这里不再赘述,我们主要关注增量修改。 在WineShopIndexTest测试类中,编写单元测试:
@Test
void testUpdateWineShopDocument() throws IOException {
    // 1.准备Request
    UpdateRequest request = new UpdateRequest("wineshop""61083");
    // 2.准备请求参数
    request.doc(
            "price""952",
            "starName""四钻"
    );
    // 3.发送请求
    client.update(request, RequestOptions.DEFAULT);
}

3.5. RestHighLevelClient批量导入文档

语法说明

批量处理BulkRequest,其本质就是将多个普通的CRUD请求组合在一起发送。其中提供了一个add方法,用来添加其他请求:

RestClient操作 Elasticsearch(ES)索引库和文档可以看到,能添加的请求包括:

  • IndexRequest,也就是新增
  • UpdateRequest,也就是修改
  • DeleteRequest,也就是删除

因此Bulk中添加了多个IndexRequest,就是批量新增功能了。示例:Java代码,依然是三步走


    1. 创建Request对象。这里是BulkRequest

    1. 准备参数。批处理的参数,就是其它Request对象,这里就是多个IndexRequest

    1. 发起请求。这里是批处理,调用的方法为client.bulk()方法

WineShopIndexTest测试类中,编写单元测试:

/**
 * 
 * 批量导入wineShop文档
 */

@Test
void testBulkRequest() throws IOException {
    // 批量查询酒店数据
    List<WineShop> wineShops = wineShopService.list();

    // 1.创建Request
    BulkRequest request = new BulkRequest();
    // 2.准备参数,添加多个新增的Request
    for (WineShop wineShop : wineShops) {
        // 2.1.转换为文档类型wineShopDoc
        WineShopDoc hotelDoc = new WineShopDoc(wineShop);
        // 2.2.创建新增文档的Request对象
        request.add(new IndexRequest("wineshop")
                .id(hotelDoc.getId().toString())
                .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
    }
    // 3.发送请求
    client.bulk(request, RequestOptions.DEFAULT);
}

通过指令查询:GET /wineShop/_searchRestClient操作 Elasticsearch(ES)索引库和文档

总结

JavaRestClient操作elasticsearch的流程基本类似。核心是client.indices()方法来获取索引库的操作对象。

索引库操作的基本步骤

  • 1.初始化RestHighLevelClient
  • 2.创建XxxIndexRequest。XXX是Create、Get、Delete
  • 3.准备DSL( Create时需要,其它是无参)
  • 4.发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete

文档操作的基本步骤

  • 1.初始化RestHighLevelClient
  • 2.创建XxxRequest。XXX是Index、Get、Update、Delete、Bulk
  • 3.准备参数(Index、Update、Bulk时需要)
  • 4.发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete、bulk
  • 5.解析结果(Get时需要)




如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

原文始发于微信公众号(springboot葵花宝典):RestClient操作 Elasticsearch(ES)索引库和文档

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/182893.html

(1)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!