SpringCloud 微服务全栈体系(十五)

第十一章 分布式搜索引擎 elasticsearch

五、RestClient 操作文档

  • 为了与索引库操作分离,再次参加一个测试类,做两件事情:

    • 初始化 RestHighLevelClient
    • 酒店数据在数据库,需要利用 IHotelService 去查询,所以注入这个接口
package com.alex.hotel;import com.alex.hotel.pojo.Hotel;
import com.alex.hotel.service.IHotelService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.io.IOException;
import java.util.List;@SpringBootTest
public class HotelDocumentTest {@Autowiredprivate IHotelService hotelService;private RestHighLevelClient client;@BeforeEachvoid setUp() {this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://192.168.150.101:9200")));}@AfterEachvoid tearDown() throws IOException {this.client.close();}
}

1. 新增文档

  • 要将数据库的酒店数据查询出来,写入 elasticsearch 中。
1.1 索引库实体类
  • 数据库查询后的结果是一个 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;
}
  • 与索引库结构存在差异:

    • longitude 和 latitude 需要合并为 location
  • 因此,需要定义一个新的类型,与索引库结构吻合:

package com.alex.hotel.pojo;import lombok.Data;
import lombok.NoArgsConstructor;@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();}
}
1.2 语法说明
  • 新增文档的 DSL 语句如下:
POST /{索引库名}/_doc/1
{"name": "Jack","age": 21
}
  • 对应的 java 代码如图:

在这里插入图片描述

  • 可以看到与创建索引库类似,同样是三步走:

    • 创建 Request 对象
    • 准备请求参数,也就是 DSL 中的 JSON 文档
    • 发送请求
  • 变化的地方在于,这里直接使用 client.xxx()的 API,不再需要 client.indices()了。

1.3 完整代码
  • 导入酒店数据,基本流程一致,但是需要考虑几点变化:

    • 酒店数据来自于数据库,我们需要先查询出来,得到 hotel 对象
    • hotel 对象需要转为 HotelDoc 对象
    • HotelDoc 需要序列化为 json 格式
  • 因此,代码整体步骤如下:

    • 根据 id 查询酒店数据 Hotel
    • 将 Hotel 封装为 HotelDoc
    • 将 HotelDoc 序列化为 JSON
    • 创建 IndexRequest,指定索引库名和 id
    • 准备请求参数,也就是 JSON 文档
    • 发送请求
  • 在 hotel-demo 的 HotelDocumentTest 测试类中,编写单元测试:

@Test
void testAddDocument() throws IOException {// 1.根据id查询酒店数据Hotel hotel = hotelService.getById(61083L);// 2.转换为文档类型HotelDoc hotelDoc = new HotelDoc(hotel);// 3.将HotelDoc转jsonString json = JSON.toJSONString(hotelDoc);// 1.准备Request对象IndexRequest request = new IndexRequest("hotel").id(hotelDoc.getId().toString());// 2.准备Json文档request.source(json, XContentType.JSON);// 3.发送请求client.index(request, RequestOptions.DEFAULT);
}

2. 查询文档

2.1 语法说明
  • 查询的 DSL 语句如下:
GET /hotel/_doc/{id}
  • 非常简单,因此代码大概分两步:

    • 准备 Request 对象
    • 发送请求
  • 不过查询的目的是得到结果,解析为 HotelDoc,因此难点是结果的解析。完整代码如下:

请添加图片描述

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

  • 与之前类似,也是三步走:

    • 准备 Request 对象。这次是查询,所以是 GetRequest
    • 发送请求,得到结果。因为是查询,这里调用 client.get()方法
    • 解析结果,就是对 JSON 做反序列化
2.2 完整代码

在 hotel-demo 的 HotelDocumentTest 测试类中,编写单元测试:

@Test
void testGetDocumentById() throws IOException {// 1.准备RequestGetRequest request = new GetRequest("hotel", "61082");// 2.发送请求,得到响应GetResponse response = client.get(request, RequestOptions.DEFAULT);// 3.解析响应结果String json = response.getSourceAsString();HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);System.out.println(hotelDoc);
}

3. 删除文档

  • 删除的 DSL 为是这样的:
DELETE /hotel/_doc/{id}
  • 与查询相比,仅仅是请求方式从 DELETE 变成 GET,可以想象 Java 代码应该依然是三步走:

    • 准备 Request 对象,因为是删除,这次是 DeleteRequest 对象。要指定索引库名和 id
    • 准备参数,无参
    • 发送请求。因为是删除,所以是 client.delete()方法
  • 在 hotel-demo 的 HotelDocumentTest 测试类中,编写单元测试:

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

4. 修改文档

4.1 语法说明
  • 修改讲过两种方式:

    • 全量修改:本质是先根据 id 删除,再新增
    • 增量修改:修改文档中的指定字段值
  • 在 RestClient 的 API 中,全量修改与新增的 API 完全一致,判断依据是 ID:

    • 如果新增时,ID 已经存在,则修改
    • 如果新增时,ID 不存在,则新增
  • 这里不再赘述,主要关注增量修改。

  • 代码示例如图:

在这里插入图片描述

  • 与之前类似,也是三步走:

    • 准备 Request 对象。这次是修改,所以是 UpdateRequest
    • 准备参数。也就是 JSON 文档,里面包含要修改的字段
    • 更新文档。这里调用 client.update()方法
4.2 完整代码
  • 在 hotel-demo 的 HotelDocumentTest 测试类中,编写单元测试:
@Test
void testUpdateDocument() throws IOException {// 1.准备RequestUpdateRequest request = new UpdateRequest("hotel", "61083");// 2.准备请求参数request.doc("price", "952","starName", "四钻");// 3.发送请求client.update(request, RequestOptions.DEFAULT);
}

5. 批量导入文档

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

  • 步骤如下:

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

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

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

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

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

在这里插入图片描述

  • 能添加的请求包括:

    • IndexRequest,也就是新增
    • UpdateRequest,也就是修改
    • DeleteRequest,也就是删除
  • 因此 Bulk 中添加了多个 IndexRequest,就是批量新增功能了。

  • 其实还是三步走:

    • 创建 Request 对象。这里是 BulkRequest
    • 准备参数。批处理的参数,就是其它 Request 对象,这里就是多个 IndexRequest
    • 发起请求。这里是批处理,调用的方法为 client.bulk()方法
  • 在导入酒店数据时,将上述代码改造成 for 循环处理即可。

5.2 完整代码
  • 在 hotel-demo 的 HotelDocumentTest 测试类中,编写单元测试:
@Test
void testBulkRequest() throws IOException {// 批量查询酒店数据List<Hotel> hotels = hotelService.list();// 1.创建RequestBulkRequest request = new BulkRequest();// 2.准备参数,添加多个新增的Requestfor (Hotel hotel : hotels) {// 2.1.转换为文档类型HotelDocHotelDoc 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);
}

6. 小结

  • 文档操作的基本步骤:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153098.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux shell编程学习笔记28:脚本调试 set命令

0 引入 在Linux Shell 脚本编程的过程中&#xff0c;编写简单功能的脚本&#xff0c;代码不多&#xff0c;一般阅读起来没什么难度&#xff0c;有问题也比较有查出原因和修正。但是当脚本要实现的功能较多&#xff0c;代码变得较为复杂时&#xff0c;阅读起来就不那么容易看明…

一道简单的积分题目

题目如下图&#xff1a; 解法1&#xff1a; 解法2&#xff1a; 解法3&#xff1a; 错误做法&#xff1a; 在 x ∈ ( 0 , ∞ ) 上有 ln ⁡ x < x &#xff0c;令 f ( x ) ln ⁡ x 1 x 2 &#xff0c; g ( x ) &#xff1d; x 1 x 2 ∴ f ( x ) < g ( x ) &#x…

Qt按钮大全续集(QCommandLinkButton和QDialogButtonBox )

## QCommandLinkButton 控件简介 QCommandLinkButton 控件中文名是“命令链接按钮”。QCommandLinkButton 继承QPushButton。CommandLinkButton 控件和 RadioButton 相似,都是用于在互斥选项中选择一项。表面上同平面按钮一样,但是 CommandLinkButton 除带有正常的按钮上的文…

SpringCloud之Feign

文章目录 前言一、Feign的介绍二、定义和使用Feign客户端1、导入依赖2、添加EnableFeignClients注解3、编写FeignClient接口4、用Feign客户端代替RestTemplate 三、自定义Feign的配置1、配置文件方式全局生效局部生效 2、java代码方式 四、Feign的性能优化连接池配置 五、Feign…

代码随想录算法训练营第六十天丨 单调栈03

84.柱状图中最大的矩形 思路 单调栈 本地单调栈的解法和接雨水的题目是遥相呼应的。 为什么这么说呢&#xff0c;42. 接雨水 (opens new window)是找每个柱子左右两边第一个大于该柱子高度的柱子&#xff0c;而本题是找每个柱子左右两边第一个小于该柱子的柱子。 这里就涉…

从入门到精通,mac电脑录屏软件使用教程!

“mac电脑怎么录屏呀&#xff0c;刚买了一台mac电脑&#xff0c;用了几个月感觉挺流畅的&#xff0c;最近因为工作原因&#xff0c;需要用到录屏功能&#xff0c;但是我不会操作&#xff0c;想问问大家有没有简单易懂的录屏教程&#xff0c;谢谢啦。” 在日常生活中&#xff0…

几个强力的nodejs库

几个强力的nodejs库 nodejs被视为许多Web开发人员的理想运行时环境。 nodejs的设计是为了在运行时中使用JavaScript编写的代码&#xff0c;它是世界上最流行的编程语言之一&#xff0c;并允许广泛的开发者社区构建服务器端应用程序。 nodejs提供了通过JavaScript库重用代码的…

FastJsonAPI

maven项目 pom.xml <dependencies><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.26</version></dependency><dependency><groupId>junit</groupId>&l…

Java读写Jar

Java提供了读写jar的类库Java.util.jar&#xff0c;Java获取解析jar包的工具类如下&#xff1a; import java.io.File; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.HashMap; import …

【图像分类】【深度学习】【Pytorch版本】ResNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】 ResNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 ResNet模型算法详解前言ResNet讲解Deep residual learning framework(深度残差学习框架)残差结构(Residuals)ResNet模型结构 ResNet Pytorch代码完整代码总结 前…

【练习】检测U盘并自动复制内容到电脑的软件

软件作用&#xff1a; 有U盘插在电脑上后&#xff0c;程序会检测到U盘的路径。 自己可以提前设置一个保存复制文件的路径或者使用为默认保存的复制路径&#xff08;默认为桌面&#xff0c;可自行修改&#xff09;。 检测到U盘后程序就会把U盘的文件复制到电脑对应的…

PyTorch微调终极指南1:预训练模型调整

如今&#xff0c;在训练深度学习模型时&#xff0c;通过根据自己的数据微调预训练模型来进行迁移学习&#xff08;transfer learning&#xff09;已成为首选方法。 通过微调这些模型&#xff0c;我们可以利用他们的专业知识并使它们适应我们的特定任务&#xff0c;从而节省宝贵…

【miniQMT实盘量化4】获取实时行情数据

前言 上篇&#xff0c;我们介绍了如何获取历史数据&#xff0c;有了历史数据&#xff0c;我们可以进行分析和回测。但&#xff0c;下一步&#xff0c;我们更需要的是实时数据&#xff0c;只有能有效的监控实时行情数据&#xff0c;才能让我们变成市场上的“千里眼&#xff0c;…

从0开始学习JavaScript--深入探究JavaScript类型化数组

JavaScript类型化数组是一种特殊的数组类型&#xff0c;引入了对二进制数据的更底层的操作。这种数组提供了对内存中的二进制数据直接进行读写的能力&#xff0c;为处理图形、音频、视频等大规模数据提供了高效的手段。本文将深入探讨JavaScript类型化数组的基本概念、常见类型…

场景交互与场景漫游-对象选取(8-2)

对象选取示例的代码如程序清单8-11所示&#xff1a; /******************************************* 对象选取示例 *************************************/ // 对象选取事件处理器 class PickHandler :public osgGA::GUIEventHandler { public:PickHandler() :_mx(0.0f), _my…

48. 旋转图像

给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&…

用平板当电脑副屏(spacedesk)双端分享

文章目录 1.准备工作2.操作流程1. 打开spacedesk点击2. 勾选USB Cable Android3. 用数据线连接移动端和pc端&#xff0c;选择仅充电4. 打开安装好的spacedesk 记得在win系统中设置扩展显示器&#xff1a; 1.准备工作 下载软件spacedesk Driver Console pc端&#xff1a; 移动…

macos苹果电脑清理软件有哪些?cleanmymac和腾讯柠檬哪个好

MacOS是一款优秀的操作系统&#xff0c;但是随着使用时间的增加&#xff0c;它也会产生一些不必要的垃圾文件&#xff0c;占用磁盘空间和内存资源&#xff0c;影响系统的性能和稳定性。为了保持MacOS的清洁和高效&#xff0c;我们需要使用一些专业的清理软件来定期扫描和清除这…

Pandas数据集的合并与连接merge()方法_Python数据分析与可视化

数据集的合并与连接 merge()解析merge()的主要参数 merge()解析 merge()可根据一个或者多个键将不同的DataFrame连接在一起&#xff0c;类似于SQL数据库中的合并操作。 数据连接的类型 一对一的连接&#xff1a; df1 pd.DataFrame({employee: [Bob, Jake, Lisa, Sue], grou…

【Linux】:体系结构与进程概念

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关Linux体系结构和进程的知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入…