网站开发与设计课程时间,如何用wordpress快速建站,优化网站seo策略,做网站要看什么书elasticsearch[一]-索引库操作(轻松创建)、文档增删改查、批量写入(效率倍增)
1、初始化 RestClient
在 elasticsearch 提供的 API 中#xff0c;与 elasticsearch 一切交互都封装在一个名为 RestHighLevelClient 的类中#xff0c;必须先完成这个对象的初始化#xff0c;…elasticsearch[一]-索引库操作(轻松创建)、文档增删改查、批量写入(效率倍增)
1、初始化 RestClient
在 elasticsearch 提供的 API 中与 elasticsearch 一切交互都封装在一个名为 RestHighLevelClient 的类中必须先完成这个对象的初始化建立与 elasticsearch 的连接。
分为三步
1引入 es 的 RestHighLevelClient 依赖
dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactId
/dependency
2因为 SpringBoot 默认的 ES 版本是 7.6.2所以我们需要覆盖默认的 ES 版本
propertiesjava.version1.8/java.versionelasticsearch.version7.12.1/elasticsearch.version
/properties
3初始化 RestHighLevelClient
初始化的代码如下
RestHighLevelClient client new RestHighLevelClient(RestClient.builder(HttpHost.create(http://xxx.xxx.xxx.xxx:9200)
));
这里为了单元测试方便我们创建一个测试类 HotelIndexTest然后将初始化的代码编写在 BeforeEach 方法中
package cn.itcast.hotel;import org.apache.http.HttpHost;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;import java.io.IOException;public class HotelIndexTest {private RestHighLevelClient client;BeforeEachvoid setUp() {this.client new RestHighLevelClient(RestClient.builder(HttpHost.create(http://xxx.xxx.xxx.xxx:9200)));}AfterEachvoid tearDown() throws IOException {this.client.close();}
}
1.1、创建索引库
创建索引库的 API 如下 代码分为三步
1创建 Request 对象。因为是创建索引库的操作因此 Request 是 CreateIndexRequest。2添加请求参数其实就是 DSL 的 JSON 参数部分。因为 json 字符串很长这里是定义了静态字符串常量 MAPPING_TEMPLATE让代码看起来更加优雅。3发送请求client.indices() 方法的返回值是 IndicesClient 类型封装了所有与索引库操作有关的方法。
完整示例
在 hotel-demo 的 cn.itcast.hotel.constants 包下创建一个类定义 mapping 映射的 JSON 字符串常量
package cn.itcast.hotel.constants;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);
}
1.2、删除索引库
删除索引库的 DSL 语句非常简单
DELETE /hotel
与创建索引库相比
请求方式从 PUT 变为 DELTE请求路径不变无请求参数
所以代码的差异注意体现在 Request 对象上。依然是三步走
1创建 Request 对象。这次是 DeleteIndexRequest 对象2准备参数。这里是无参3发送请求。改用 delete 方法
在 hotel-demo 中的 HotelIndexTest 测试类中编写单元测试实现删除索引
Test
void testDeleteHotelIndex() throws IOException {// 1.创建Request对象DeleteIndexRequest request new DeleteIndexRequest(hotel);// 2.发送请求client.indices().delete(request, RequestOptions.DEFAULT);
}
1.3、判断索引库是否存在
判断索引库是否存在本质就是查询对应的 DSL 是
GET /hotel
因此与删除的 Java 代码流程是类似的。依然是三步走
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 ? 索引库已经存在 : 索引库不存在);
}
1.4、总结
JavaRestClient 操作 elasticsearch 的流程基本类似。核心是 client.indices() 方法来获取索引库的操作对象。
索引库操作的基本步骤
初始化 RestHighLevelClient创建 XxxIndexRequest。XXX 是 Create、Get、Delete准备 DSL Create 时需要其它是无参发送请求。调用 RestHighLevelClient#indices().xxx() 方法xxx 是 create、exists、delete
2、RestClient 操作文档
为了与索引库操作分离我们再次参加一个测试类做两件事情
初始化 RestHighLevelClient我们的酒店数据在数据库需要利用 IHotelService 去查询所以注入这个接口
package cn.itcast.hotel;import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.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();}
}
2.1、新增文档
我们要将数据库的酒店数据查询出来写入 elasticsearch 中。
2.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 cn.itcast.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();}
}
2.1.2. 语法说明
新增文档的 DSL 语句如下
POST /{索引库名}/_doc/1
{name: Jack,age: 21
}
对应的 java 代码如图
可以看到与创建索引库类似同样是三步走
1创建 Request 对象2准备请求参数也就是 DSL 中的 JSON 文档3发送请求
变化的地方在于这里直接使用 client.xxx() 的 API不再需要 client.indices() 了。
2.1.3、完整代码
我们导入酒店数据基本流程一致但是需要考虑几点变化
酒店数据来自于数据库我们需要先查询出来得到 hotel 对象hotel 对象需要转为 HotelDoc 对象HotelDoc 需要序列化为 json 格式
因此代码整体步骤如下
1根据 id 查询酒店数据 Hotel2将 Hotel 封装为 HotelDoc3将 HotelDoc 序列化为 JSON4创建 IndexRequest指定索引库名和 id5准备请求参数也就是 JSON 文档6发送请求
在 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、查询文档
2.2.1、语法说明
查询的 DSL 语句如下
GET /hotel/_doc/{id}
非常简单因此代码大概分两步
准备 Request 对象发送请求
不过查询的目的是得到结果解析为 HotelDoc因此难点是结果的解析。完整代码如下
可以看到结果是一个 JSON其中文档放在一个_source属性中因此解析就是拿到_source反序列化为 Java 对象即可。
与之前类似也是三步走
1准备 Request 对象。这次是查询所以是 GetRequest2发送请求得到结果。因为是查询这里调用 client.get() 方法3解析结果就是对 JSON 做反序列化
2.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);
}
2.3. 删除文档
删除的 DSL 为是这样的
DELETE /hotel/_doc/{id}
与查询相比仅仅是请求方式从 DELETE 变成 GET可以想象 Java 代码应该依然是三步走
1准备 Request 对象因为是删除这次是 DeleteRequest 对象。要指定索引库名和 id2准备参数无参3发送请求。因为是删除所以是 client.delete() 方法
在 hotel-demo 的 HotelDocumentTest 测试类中编写单元测试
Test
void testDeleteDocument() throws IOException {// 1.准备RequestDeleteRequest request new DeleteRequest(hotel, 61083);// 2.发送请求client.delete(request, RequestOptions.DEFAULT);
}
2.4、修改文档
2.4.1、语法说明
修改我们讲过两种方式
全量修改本质是先根据 id 删除再新增增量修改修改文档中的指定字段值
在 RestClient 的 API 中全量修改与新增的 API 完全一致判断依据是 ID
如果新增时ID 已经存在则修改如果新增时ID 不存在则新增
这里不再赘述我们主要关注增量修改。
代码示例如图
与之前类似也是三步走
1准备 Request 对象。这次是修改所以是 UpdateRequest2准备参数。也就是 JSON 文档里面包含要修改的字段3更新文档。这里调用 client.update() 方法
2.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);
}
2.5、批量导入文档
案例需求利用 BulkRequest 批量将数据库数据导入到索引库中。
步骤如下 利用 mybatis-plus 查询酒店数据 将查询到的酒店数据Hotel转换为文档类型数据HotelDoc 利用 JavaRestClient 中的 BulkRequest 批处理实现批量新增文档
2.5.1. 语法说明
批量处理 BulkRequest其本质就是将多个普通的 CRUD 请求组合在一起发送。
其中提供了一个 add 方法用来添加其他请求
可以看到能添加的请求包括
IndexRequest也就是新增UpdateRequest也就是修改DeleteRequest也就是删除
因此 Bulk 中添加了多个 IndexRequest就是批量新增功能了。示例
其实还是三步走
1创建 Request 对象。这里是 BulkRequest2准备参数。批处理的参数就是其它 Request 对象这里就是多个 IndexRequest3发起请求。这里是批处理调用的方法为 client.bulk() 方法
我们在导入酒店数据时将上述代码改造成 for 循环处理即可。
2.5.2. 完整代码
在 hotel-demo 的 HotelDocumentTest 测试类中编写单元测试 /*** 批量导入es* throws IOException*/Testvoid testBatchImportDocument() throws IOException {// 1、批量查询数据库数据ListHotel list hotelService.list();// 2、创建 request 对象BulkRequest request new BulkRequest();// 3、转换文档格式for (Hotel hotel : list) {HotelDoc hotelDoc new HotelDoc(hotel);request.add(new IndexRequest(hotel).id(hotel.getId().toString()).source(JSON.toJSONString(hotelDoc), XContentType.JSON));}// 4、发送请求client.bulk(request, RequestOptions.DEFAULT);}
2.6. 小结
文档操作的基本步骤
初始化 RestHighLevelClient创建 XxxRequest。XXX 是 Index、Get、Update、Delete、Bulk准备参数Index、Update、Bulk 时需要发送请求。调用 RestHighLevelClient#.xxx() 方法xxx 是 index、get、update、delete、bulk解析结果Get 时需要
参考链接https://www.cnblogs.com/DeryKong/p/17002492.html