Elasticsearch学习笔记-p3(RestClient操作文档)

Posted LL.LEBRON

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch学习笔记-p3(RestClient操作文档)相关的知识,希望对你有一定的参考价值。


视频指路👉 B站黑马微服务超级推荐!!

RestClient操作文档

1.初始化RestClient

在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。

分为三步:

(1)引入es的RestHighLevelClient依赖:

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

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

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

(3)初始化RestHighLevelClient

RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
    //填自己的服务器ip地址
    HttpHost.create("http://192.168.150.101:9200")
));

这里为了单元测试方便,我们创建一个测试类HotelIndexTest,然后将初始化的代码编写在@BeforeEach方法中:

public class HotelIndexTest 
    private RestHighLevelClient client;

    //初始化
    @BeforeEach
    void setUp() 
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.150.101:9200")
        ));
    
	//用完释放资源
    @AfterEach
    void tearDown() throws IOException 
        this.client.close();
    

2.索引库操作

2.1 创建索引库

代码分为三步:

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

hotel-demo的cn.itcast.hotel.constants包下,创建一个类,定义mapping映射的JSON字符串常量:

public class HotelConstants 
    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" +
            "        \\"copy_to\\": \\"all\\"\\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" +
            "        \\"copy_to\\": \\"all\\"\\n" +
            "      ,\\n" +
            "      \\"starName\\":\\n" +
            "        \\"type\\": \\"keyword\\"\\n" +
            "      ,\\n" +
            "      \\"business\\":\\n" +
            "        \\"type\\": \\"keyword\\"\\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" +
            "";

hotel-demo中的HotelIndexTest测试类中,编写单元测试,实现创建索引:

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

2.2 删除索引库

删除索引库的DSL语句:

DELETE /hotel

代码分三步:

  1. 创建Request对象。这次是DeleteIndexRequest对象
  2. 准备参数。这里是无参
  3. 发送请求。改用delete方法
@Test
void testDeleteHotelIndex() throws IOException 
    // 1.创建Request对象
    DeleteIndexRequest request = new DeleteIndexRequest("hotel");
    // 2.发送请求
    client.indices().delete(request, RequestOptions.DEFAULT);

2.3 判断索引库是否存在

判断索引库是否存在,本质就是查询,对应的DSL是:

GET /hotel

代码分三步:

  1. 创建Request对象。这次是GetIndexRequest对象
  2. 准备参数。这里是无参
  3. 发送请求。改用exists方法
@Test
void testExistsHotelIndex() throws IOException 
    // 1.创建Request对象
    GetIndexRequest request = new GetIndexRequest("hotel");
    // 2.发送请求
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    // 3.输出
    System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");

2.4 总结

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

索引库操作的基本步骤:

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

3.文档操作

在创建一个测试类HotelDocumentTest

  • 初始化RestHighLevelClient
  • 我们的酒店数据在数据库,需要利用IHotelService去查询,所以注入这个接口
@SpringBootTest
public class HotelDocumentTest 
    @Autowired
    private IHotelService hotelService;

    private RestHighLevelClient client;

    @BeforeEach
    void setUp() 
        this.client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://192.168.150.101:9200")
        ));
    

    @AfterEach
    void tearDown() throws IOException 
        this.client.close();
    

3.1 新增文档

目的:我们要将数据库的酒店数据查询出来,写入elasticsearch中。

数据库查询后的结果是一个Hotel类型的对象。结构如下:

@Data
@TableName("tb_hotel")
public class Hotel 
    @TableId(type = IdType.INPUT)
    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 longitude;
    private String latitude;
    private String pic;

因为数据库与我们的索引库结构存在差异:longitudelatitude需要合并为location

因此,我们需要定义一个新的类型HotelDoc,与索引库结构吻合:

@Data
@NoArgsConstructor
public class HotelDoc 
    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 HotelDoc(Hotel hotel) 
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", " + hotel.getLongitude();
        this.pic = hotel.getPic();
    

新增文档的DSL语句如下:

POST /索引库名/_doc/1

    "name": "Jack",
    "age": 21

注意:

与创建索引库不同的是,这里直接使用client.xxx()的API,不再需要client.indices()了

我们导入酒店数据,基本流程一致,但是需要考虑几点变化:

  • 酒店数据来自于数据库,我们需要先查询出来,得到hotel对象
  • hotel对象需要转为HotelDoc对象
  • HotelDoc需要序列化为json格式

代码如下:

@Test
void testAddDocument() throws IOException 
    // 1.根据id查询酒店数据
    Hotel hotel = hotelService.getById(61083L);
    // 2.转换为文档类型
    HotelDoc hotelDoc = new HotelDoc(hotel);
    // 3.将HotelDoc转json
    String json = JSON.toJSONString(hotelDoc);

    // 1.创建IndexRequest,指定索引库名和id
    IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());
    // 2.准备请求参数,也就是JSON文档
    request.source(json, XContentType.JSON);
    // 3.发送请求
    client.index(request, RequestOptions.DEFAULT);

3.2 查询文档

查询文档的DSL语句如下:

GET /hotel/_doc/id

注意:

查询的目的是得到结果,解析为HotelDoc,因此难点是结果的解析

从上图可以看到,结果是一个JSON,其中文档放在一个_source属性中,因此解析就是拿到_source,反序列化为Java对象即可。

代码如下:

@Test
void testGetDocumentById() throws IOException 
    // 1.准备Request。这次是查询,所以是GetRequest,要指定索引库名和id
    GetRequest request = new GetRequest("hotel", "61082");
    // 2.发送请求,得到响应。因为是查询,这里调用client.get()方法
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    // 3.解析响应结果。就是对JSON做反序列化
    String json = response.getSourceAsString();
    HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
   	//4.输出测试结果
    System.out.println(hotelDoc);

3.3 删除文档

删除文档的DSL语句如下:

DELETE /hotel/_doc/id

代码如下:

@Test
void testDeleteDocument() throws IOException 
    // 1.准备Request。次是DeleteRequest对象。要指定索引库名和id
    DeleteRequest request = new DeleteRequest("hotel", "61083");
    // 2.发送请求。因为是删除,所以是client.delete()方法
    client.delete(request, RequestOptions.DEFAULT);

3.4 修改文档

修改有两种方式:

  • 全量修改:本质是先根据id删除,再新增
  • 增量修改:修改文档中的指定字段值

RestClient的API中,全量修改与新增的API完全一致,判断依据是ID:

  • 如果新增时,ID已经存在,则修改
  • 如果新增时,ID不存在,则新增

代码如下:

@Test
void testUpdateDocument() throws IOException 
    // 1.准备Request。这次是修改,所以是UpdateRequest。要指定索引库名和id
    UpdateRequest request = new UpdateRequest("hotel", "61083");
    // 2.准备请求参数。也就是JSON文档,里面包含要修改的字段
    request.doc(
        "price", "952", //两个一对
        "starName", "四钻"
    );
    // 3.发送请求。更新文档。这里调用client.update()方法
    client.update(request, RequestOptions.DEFAULT);

3.5 批量导入文档

案例需求:利用BulkRequest批量将数据库数据导入到索引库中。

步骤如下:

  • 利用mybatis-plus查询酒店数据

  • 将查询到的酒店数据(Hotel)转换为文档类型数据(HotelDoc)

  • 利用JavaRestClient中的BulkRequest批处理,实现批量新增文档

批量处理BulkRequest,其本质就是将多个普通的CRUD请求组合在一起发送。

其中提供了一个add方法,用来添加其他请求:

可以看到,能添加的请求包括:

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

因此Bulk中添加了多个IndexRequest,就是批量新增功能了。示例:

代码如下:

@Test
void testBulkRequest() throws IOException 
    // 批量查询酒店数据
    List<Hotel> hotels = hotelService.list();
    // 1.创建Request
    BulkRequest request = new BulkRequest();
    // 2.准备参数,添加多个新增的Request
    for (Hotel hotel : hotels) 
        // 2.1.转换为文档类型HotelDoc
        HotelDoc hotelDoc = new HotelDoc(hotel);
        // 2.2.创建新增文档的Request对象
        request.add(new IndexRequest("hotel")
                    .id(hotelDoc.getId().toString())
                    .source(JSON.toJSONString(hotelDoc), XContentType.JSON));
    
    // 3.发送请求
    client.bulk(request, RequestOptions.DEFAULT);

3.6 总结

文档操作的基本步骤:

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


最后喜欢的小伙伴,记得三连哦!😏🍭😘

以上是关于Elasticsearch学习笔记-p3(RestClient操作文档)的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch总结笔记

ElasticSearch笔记整理:简介REST与安装配置

P3-SQL 学习笔记

Elasticsearch的学习和理解:使用REST API与Sense

李宏毅机器学习 p3[学习笔记 ]

第130天学习打卡(ElasticSearch Rest风格说明 索引 文档 )