ElasticSearch - 基于 JavaRestClient 操作索引库和文档
目录
一、RestClient操作索引库
1.1、RestClient是什么?
1.2、JavaRestClient 实现创建、删除索引库
1.2.1、前言
1.2.1、初始化 JavaRestClient
1.2.2、创建索引库
1.2.3、判断索引库是否存在
1.2.4、删除索引库
1.3、JavaRestClient 实现文档的 CRUD
1.3.1、初始化 JavaRestClient
1.3.2、添加文档(酒店数据)到索引库
1.3.3、根据 id 查询酒店数据
1.3.4、根据 id 修改酒店数据
1.3.5、根据 id 删除文档数据
1.3.6、批量导入文档
一、RestClient操作索引库
1.1、RestClient是什么?
前面我们已经了解了如何利用 DSL 语句去操作 es 的索引库和文档,但作为 java 程序员,将来肯定是要通过 java 代码去操作 es 的,那么想要实现这些,就需要通过 es 官方提供的 RestClient 实现.
RestClient 实际上就是 es 官方提供的各种语言的客户端,他的作用就是帮助我们组装 DSL 语句,然后发送 http 请求给 es 服务器,而我们只需要通过 java 代码将请求发送给客户端,然后客户端就会帮我们来处理剩下的这些事情.
官方文档地址:Elasticsearch Clients | Elastic

1.2、JavaRestClient 实现创建、删除索引库
1.2.1、前言
这里我将以一个 酒店 demo 工程来演示 JavaRestClient 的操作.
具体来讲,这是一个酒店的数据,创建的 sql 如下:
CREATE TABLE `tb_hotel` (`id` bigint(20) NOT NULL COMMENT '酒店id',`name` varchar(255) NOT NULL COMMENT '酒店名称;例:7天酒店',`address` varchar(255) NOT NULL COMMENT '酒店地址;例:航头路',`price` int(10) NOT NULL COMMENT '酒店价格;例:329',`score` int(2) NOT NULL COMMENT '酒店评分;例:45,就是4.5分',`brand` varchar(32) NOT NULL COMMENT '酒店品牌;例:如家',`city` varchar(32) NOT NULL COMMENT '所在城市;例:上海',`star_name` varchar(16) DEFAULT NULL COMMENT '酒店星级,从低到高分别是:1星到5星,1钻到5钻',`business` varchar(255) DEFAULT NULL COMMENT '商圈;例:虹桥',`latitude` varchar(32) NOT NULL COMMENT '纬度;例:31.2497',`longitude` varchar(32) NOT NULL COMMENT '经度;例:120.3925',`pic` varchar(255) DEFAULT NULL COMMENT '酒店图片;例:/img/1.jpg',PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
之后我们创建 索引库 的时候,就需要基于上述 sql 数据,来考虑 mapping 约束.
1.2.1、初始化 JavaRestClient
a)引入 es 的 RestHighLevelClient 依赖
<dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId></dependency>
b)由于 SpringBoot 默认的 ES 版本是 7.6.2,因此这里我们需要覆盖默认的 ES 版本.
在 yml 配置文件中添加如下版本信息即可.
<properties><java.version>1.8</java.version> <elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
c)初始化 RestHighLevelClient.
这里我们创建一个测试类 HotelIndexTest ,用来演示 RestClient 操作的相关方法.
@SpringBootTest
class HotelIndexTest {private RestHighLevelClient client;@BeforeEachpublic void setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http//云服务器ip:9200")//将来如果是集群,这里还可以通过 HttpHost.create 继续连接多个节点));}@AfterEachpublic void tearDown() throws IOException {client.close();}}
1.2.2、创建索引库
这里就需要根据前面提供的表结构来考虑 mapping 该如何建立.
具体的要考虑:字段名、数据类型、是否参与搜索、是否分词、如果分词,分词器是什么?
这里可以先使用 Kibana 来编写.
PUT /hotel
{"mappings": {"properties": {"id": { // id 按照数据库那边的定义,这里因该类型设置为 long// 但是这里比较特殊,在索引库中 id 比较特殊,将来都是字符串类型.// 又因为 id 将来不做分词处理,因此是 keyword 类型// id 将来肯定要参与 crud ,因此 index 就默认为 true 即可."type": "keyword"},"name": {// 酒店的名字需要搜索和分词."type": "text","analyzer": "ik_max_word", "copy_to": "all"},"address": {// 有时候我们需要根据地址来查询附近的酒店,分词也是有必要的("例如 徐汇龙华西路315弄58号")"type": "text","analyzer": "ik_max_word","copy_to": "all"},"price": {//将来要根据价格范围过滤酒店,所以需要搜索,分词就没必要了."type": "integer"},"score": {//这里就和 price 一样了"type": "integer"},"brand": {//酒店的品牌肯定是不需要分词了,但一定需要参与搜索."type": "keyword","copy_to": "all"},"city": {//城市名字不要分词,但需要参与搜索"type": "keyword","copy_to": "all"},"star_name": {//一星、二星、三星... 分词是没有意义的,组合起来才有意义.//有的人就想住5星酒店,那肯定要参与搜索."type": "keyword"},"business": {//商圈比如: 虹桥、外滩... 这些肯定不需要分词,但一定需要参与搜索."type": "keyword","copy_to": "all"},"pic": {//图片这里就是一个 url 路径,不需要分词,也没有人会搜这个 url//因此就这个 url 就可以当作关键字来处理."type": "keyword","index": false},"location": {//在 es 中有两种特殊的方式,专门来表示地理坐标//"geo_point": 表示地图上的点//"geo_shape": 表示地图上的区域,也就是多个点组成.//那么酒店肯定是属于一个点(毕竟从地球上看,再大的酒店也不过是点)// geo_point 里面由 经度 和 纬度 组成,并且是这两拼在一起组成的字符串"type": "geo_point"},"all": {// 将来 name、address、brand... 这些字段大概率都需要参与搜索// 也就意味着用户输入的的关键字,我们后端都需要根据多个字来搜.// 并且我们可以想象以下 es 作搜索的时候, 根据多个字段去搜索的效率肯定是要比一个字段搜索效率要低//这里对比以下数据库就清楚了.//最重要的是, 我们也希望用户输入名称就能搜到相关的内容, 用户输入品牌也能搜到相关内容...// es 就中有一个字段 "copy_to", 就是将当前字段的值拷贝到指定字段.//这里我们就将需要搜索的字段都拷贝到 all 这个字段中就 ok//这也就实现了在一个字段里, 搜索到多个字段的内容."type": "text","analyzer": "ik_max_word"}}}
}
自定义 all 字段的解读:
将来 name、address、brand... 这些字段大概率都需要参与搜索,也就意味着用户输入的的关键字,我们后端都需要根据多个字来搜,并且我们可以想象以下 es 作搜索的时候, 根据多个字段去搜索的效率肯定是要比一个字段搜索效率要低,这里对比以下数据库就清楚了~
最重要的是, 我们也希望用户输入名称就能搜到相关的内容, 用户输入品牌也能搜到相关内容... es 就中有一个字段 "copy_to", 就是将当前字段的值拷贝到指定字段。这里我们就将需要搜索的字段都拷贝到 all 这个字段中就 ok ,实现了在一个字段里, 搜索到多个字段的内容.
而且这里还做了优化,并不是真的吧文档拷贝进去,而是创建索引,将来你去查的时候,是看不到这些字段,但搜却能搜到(类似于根据指针找到数据所在位置).
创建索引库代码如下:
@Testpublic void testCreateHotelIndex() throws IOException {//1.创建 Request 对象CreateIndexRequest request = new CreateIndexRequest("hotel");//2.编写请求参数(MAPPING_TEMPLATE 是一个静态常量,内容是创建索引库的 DSL 语句)request.source(MAPPING_TEMPLATE, XContentType.JSON);//3.发起请求client.indices().create(request, RequestOptions.DEFAULT);}
- CreateIndexRequest 的构造参数就是请求创建的索引库的名字.
- MAPPING_TEMPLATE:是自定义的静态常量,内容是创建索引库的 DSL 语句.
- client.indices(): 这个方法的返回值是一个对象(indices 是 index 的复数形式),包含了操作索引库的所有方法.
- RequestOptions.DEFAULT :就表示走默认的方法.

执行以后发现运行成功了~

之后去 Elastic DevTools 上去 GET,就可以看到新增的索引库了~

1.2.3、判断索引库是否存在
判断索引库是否存在代码如下:
@Testpublic void testExistsHotelIndex() throws IOException {//1.创建 Request 对象GetIndexRequest request = new GetIndexRequest("hotel");//2.发送请求boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println(exists);}
很多时候,我们先写 client.indices().exists 就可以之间看出需要什么参数

运行以后,可以看到通过了(true 是因为上个案例添加索引库是存在的).

1.2.4、删除索引库
判断删除索引库代码如下:
@Testpublic void testDeleteHotelIndex() throws IOException {//1.创建 Request 对象DeleteIndexRequest request = new DeleteIndexRequest("hotel");//2.发送请求client.indices().delete(request, RequestOptions.DEFAULT);}

之后再查询就发现查询不到了,表明删除成功.

1.3、JavaRestClient 实现文档的 CRUD
1.3.1、初始化 JavaRestClient
这里的初始化操作和操作索引库的初始化一样(本质上都是连接 JavaRestClient 客户端).
@SpringBootTest
class HotelDocumentTest {private RestHighLevelClient client;@BeforeEachpublic void setUp() {client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://云服务器ip:9200")));}@AfterEachpublic void tearDown() throws IOException {client.close();}}
1.3.2、添加文档(酒店数据)到索引库
Ps:操作文档前需要先创建对应索引库
这里我先通过 MyBatis-Puls 从数据库拿到数据,然后添加文档.
实体类如下(这里重写构造方法主要是为了 location 属性(地理位置),将经度,纬度合二为一):
@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();}
}
@NoArgsConstructor:生成无参构造.
编写添加文档代码:
@Testpublic void testAddDocument() throws IOException {//1.获取酒店数据Hotel hotel = hotelService.getById(5865979L);//2.转化文档(主要是地理位置)HotelDoc hotelDoc = new HotelDoc(hotel);//3.转化为 JSON 格式String hotelJson = objectMapper.writeValueAsString(hotelDoc);//4.构造请求IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());//5.添加请求参数(json 格式)request.source(hotelJson, XContentType.JSON);//6.发送请求client.index(request, RequestOptions.DEFAULT);}
运行后发现通过了

在 Kibana 上查询就可以得到对应的数据

1.3.3、根据 id 查询酒店数据
这里值得注意的是:通过 client.get 查询到的是一个 GetResponse 对象,需要获取里面的原数据.
代码如下:
@Testpublic void testGetDocument() throws IOException {//1.构造请求GetRequest request = new GetRequest("hotel").id("5865979");//2.发送请求GetResponse response = client.get(request, RequestOptions.DEFAULT);//3.转化成jsonString json = response.getSourceAsString();System.out.println(json);}

运行后就可以得到对应的数据

1.3.4、根据 id 修改酒店数据
修改文档数据有两种方式(之前提到过):
- 全量更新(就是上面演示的添加文档):再次写入 id 一样的文档,就会删除旧文档,添加新文档.
- 局部更新(演示这个):只更新部分字段.
@Testpublic void testUpdateDocument() throws IOException {//1.构造请求UpdateRequest request = new UpdateRequest("hotel", "5865979");//2.填写参数request.doc("name", "地表最强酒店","price", "99999");//3.发送请求client.update(request, RequestOptions.DEFAULT);}

在 Kibana 上通过 GET 查询如下:

1.3.5、根据 id 删除文档数据
删除文档代码如下:
@Testpublic void testDeleteDocument() throws IOException {//1.构造请求DeleteRequest request = new DeleteRequest("hotel", "5865979");//2.发送请求client.delete(request, RequestOptions.DEFAULT);}
1.3.6、批量导入文档
例如导入酒店的所有数据,代码如下:
@Testpublic void testBulkDocument() throws IOException {//1.获取酒店所有数据List<Hotel> hotelList = hotelService.list();//2.构造请求BulkRequest request = new BulkRequest();//3.准备参数for(Hotel hotel : hotelList) {//转化为文档(主要是地理位置)HotelDoc hotelDoc = new HotelDoc(hotel);String json = objectMapper.writeValueAsString(hotelDoc);request.add(new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON));}//4.发送请求client.bulk(request, RequestOptions.DEFAULT);}
运行后可以看到通过了

之后再 Kibana 上随机查询一个酒店数据都是存在的


相关文章:
ElasticSearch - 基于 JavaRestClient 操作索引库和文档
目录 一、RestClient操作索引库 1.1、RestClient是什么? 1.2、JavaRestClient 实现创建、删除索引库 1.2.1、前言 1.2.1、初始化 JavaRestClient 1.2.2、创建索引库 1.2.3、判断索引库是否存在 1.2.4、删除索引库 1.3、JavaRestClient 实现文档的 CRUD 1.3…...
【人脸质量评估】MagFace:一个既可以用作人脸识别,又可以用作人脸质量评估的方法
论文题目:《MagFace: A Universal Representation for Face Recognition and Quality Assessment》-CVPR2021 论文地址:https://arxiv.org/abs/2103.06627v4 代码地址:https://github.com/IrvingMeng/MagFace...
FPGA 图像缩放 千兆网 UDP 网络视频传输,基于RTL8211 PHY实现,提供工程和QT上位机源码加技术支持
目录 1、前言版本更新说明免责声明 2、相关方案推荐UDP视频传输--无缩放FPGA图像缩放方案我这里已有的以太网方案 3、设计思路框架视频源选择ADV7611 解码芯片配置及采集动态彩条跨时钟FIFO图像缩放模块详解设计框图代码框图2种插值算法的整合与选择 UDP协议栈UDP视频数据组包U…...
智能驾驶、智能家居、智能工业中的 AI 关键基础设施,半导体厂商恩智浦的角色是什么?
我们来看一条七年前的真实新闻报道,2016 年《福布斯》在报道中提到“2020 年会有 1000 万台的自动驾驶汽车”。然而 2023 年的现在,真正实现 L4 级别自动驾驶的汽车,仍然远远没有达到这个预测的数量。 另一边,数据显示,…...
APScheduler包——python tornado框架中实现定时任务
介绍: APScheduler的全称是Advanced Python Scheduler。它是一个轻量级的 Python 定时任务调度框架。APScheduler 支持三种调度任务:固定时间间隔,固定时间点(日期),Linux 下的 Crontab 命令。同时…...
BASH shell脚本篇3——字符串处理
这篇文章介绍下BASH shell中的字符串处理的相关命令。之前有介绍过shell的其它命令,请参考: BASH shell脚本篇1——基本命令 BASH shell脚本篇2——条件命令 Bash字符串也是一种数据类型,它用于表示文本而不是数字,它是一组可能…...
【SSL】用Certbot生成免费HTTPS证书
1. 实验背景 服务器:CentOS7.x 示例域名: www.example.com 域名对应的web站点目录: /usr/local/openresty/nginx/html 2. 安装docker # yum -y install yum-utils# yum-config-manager --add-repo https://download.docker.com/linux/ce…...
报错:java.sql.SQLSyntaxErrorException: Table ‘examsys.Teacher’ doesn’t exist
Linux大小写区分,导致部署项目时MySQL出现错误 问题原因:找不到Teacher这张表。因为在windows下的mysql表名不区分大小写,所以在windows下运行项目没问题。在linux中,mysql会区分大小写,所以sql语句表名用大写的就会找…...
.NET的PLC帮助类
TCP和UDP协议: TCP(传输控制协议)和UDP(用户数据报协议)是TCP/IP协议簇中的两种核心协议。它们在传输层上提供数据传输服务,但具有不同的特性和功能。 TCP协议是一种提供可靠、面向连接的字节流服务的传输协…...
Linux中nfs:failed: Operation not supported
先给出思路: 一个简单粗暴的方式:卸载重装排除未知问题,步骤如下: 一、在 Linux 上卸载 NFS 服务器,步骤: 停止 NFS 服务: sudo service nfs-kernel-server stop如果您使用的是不同的发行版&am…...
ElasticSearch映射与模板介绍
一、前言 前面有相关系列文章介绍了ES的基本概念和各种版本SDK的使用,ES现在已升级到8.5版本,有些概念和SDK用法都有很大变化,后续ES相关的文章会以8.3版本为基准介绍一些实际中应用需要掌握的概念以及一些比较实际的例子。 二、映射 ES环…...
通过 Azure 日志分析加强云安全
Microsoft Azure 云服务在安全日志存储、访问、可伸缩性、降低成本和易于部署方面提供了巨大的优势,因此在企业中很受欢迎。 Microsoft Azure 日志记录工具(如 Log360)可帮助管理 Azure 云基础结构中所有设备和应用程序(如虚拟机…...
[H5动画制作系列 ]变量,帧频,监听器等的生命周期基础测试
模式:按照上述抓图,actions层,1帧,写初始化代码,10帧写返回代码到2帧代码,2-10帧之间一直循环。1帧及10帧代码如下: 如果程序在1-10之间循环,会反复创建变量i,多个监听器等。所以,第一帧最好执行一次即可,程序在2-10帧之间一直循环。...
基于SpringBoot的服装生产管理系统的设计与实现
目录 前言 一、技术栈 二、系统功能介绍 登录界面的实现 系统主界面的实现 用户管理模块的实现 人事安排管理模块的实现 工资管理模块的实现 考勤管理模块的实现 样板管理模块的实现 三、核心代码 1、登录模块 2、文件上传模块 3、代码封装 前言 本协力服装厂服装生…...
动态内存操作(2)
接上一篇文章http://t.csdn.cn/1ONDq,这次我们继续讲解关于动态内存的相关知识。 一、常见的动态内存错误 1.对NULL指针进行解引用操作 #include<stdio.h> #include<stdlib.h> #include<limits.h> int main() {int* p (int*)malloc(INT_MAX/4);…...
Windows-Delphi 窗口置顶
露从今夜白,月是故乡明。 1.Delphi将窗口置顶 if topHwnd <> 0 thenbeginSetWindowPos(topHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);tmr1.Enabled : True;end; 其中topHwnd是目标窗口的句柄。 2.窗口取消置顶 if topHwnd <> 0 th…...
CVE-2020-11978 Apache Airflow 命令注入漏洞分析与利用
简介 漏洞软件:Apache Airflow影响版本:< 1.10.10 环境 Vulhub 漏洞测试靶场 复现步骤 进入 /root/vulhub/airflow/CVE-2020-11978/ 目录运行以下命令启动环境 # 初始化数据库 docker compose run airflow-init # 开启服务 docker compose up -…...
面试经典算法1:DFS
一、前言 1、题目描述和代码仅供参考,如果有问题欢迎指出 2、解题代码采用acm模式(自己处理输入输出),不采用核心代码模式(只编程核心函数) 3、解题代码采用C语言(ai一键翻译任意语言ÿ…...
Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!
文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员,自己搭建网站制作网页是绕…...
SmartCode ViewerX VNC 3.11 Crack
SmartCode ViewerX VNC 查看器 ActiveX 轻松地将 VNC 查看器功能添加到您的应用程序中 SmartCode ViewerX VNC Viewer ActiveX 使开发人员可以使用一组直观的 ActiveX 属性和方法完全访问 VNC 查看器功能。借助ViewerX控件,开发人员可以轻松地为其应用程序提供屏幕共…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
VB.net复制Ntag213卡写入UID
本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
