前面的文章具体介绍了是索引库及文档的一些基本操作指令, 指令还是挺简单的; 那么实际应用场景下, 我们是如何操作 ElasticSearch 的呢?
其实 ElasticSearch 官方已经为我们提供了各种不同语言的客户端, 目的就是为了来操作 ElasticSearch, 这些客户端的本质就是组装 DSL 语句, 通过 http 请求发送给 ElasticSearch, ➽官方文档地址.
本文数据将借用某站的酒店数据库数据, 主要学习 RestClient 的含义及如何使用.
关于索引库前面的博客已经说过最关键的是 mapping 映射, 因为 mapping 里面就是索引库的结构, 字段及子字段都在 properties 中, 主要注意下面几点:
关于 RestClient 的初始化主要分为三步, 首先要做的是对 RestHighLevelClient 类的初始化, 建立与 ElasticSearch 的连接 (因为与 ElasticSearch 的一切交互都封装到了这个类中).
⅓: 引入 RestHighLevelClient 依赖
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
<version>7.17.7version>
dependency>
⅔: 检查自己的 SpringBoot 默认的 ElasticSearch 版本是哪个, 如果不是 7.17.7, 就要改成 7.17.7
1: 初始化 RestHighLevelClient
@Bean
public RestHighLevelClient client() {
return new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://172.16.**.**:9200")
));
}
针对索引库的操作在测试类中使用; 关于索引库的创建也是分为三步:
Ⅰ: 创建 Request 对象, CreateIndexRequest create = new CreateIndexRequest(“hotel”);
Ⅱ: 添加请求参数, 这里的参数就是 DSL 中 JSON 参数部分, 因为字符串比较长, 可以定义一个静态字符串常量;
Ⅲ: 发送请求, client.indices() 方法的返回值是 IndicesClient 类型, 封装了所有与索引库操作有关的方法.
@Test
void createHotelIndex() throws IOException {
CreateIndexRequest request = new CreateIndexRequest("hotel");
request.source(MAPPING_TEMPLATE, XContentType.JSON);
client.indices().create(request, RequestOptions.DEFAULT);
}
// 静态字符串常量 MAPPING_TEMPLATE
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" +
" },\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" +
" },\n" +
" \"starName\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"business\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\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" +
"}";
}
上篇博客可以看的出来删除索引库的 DSL 语句比较简单, DELETE /索引库名
, 与 创建索引库相比只不过是由 PUT 变成了 DELETE, 请求路径无需改变, 也没有任何请求参数. 当然代码还是分三步走:
Ⅰ: 创建 Request 对象, 注意这次不再是 CreateIndexRequest create 对象, 而是 DeleteIndexRequest 对象;
Ⅱ: 准备参数, 当然这里无参数;
Ⅲ: 发送请求, 改成了 delete 方法; client.indices() 方法的返回值是 IndicesClient 类型, 封装了所有与索引库操作有关的方法.
@Test
void testDeleteHotelIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
client.indices().delete(request, RequestOptions.DEFAULT);
}
查询索引库操作对应的 DSL 语句是 GET /索引库名
;
Ⅰ: 创建 Request 对象, 这次是 GetIndexRequest 对象;
Ⅱ: 准备参数, 当然这里也是无参数;
Ⅲ: 发送请求, 改成了 exists 方法; client.indices() 方法的返回值是 IndicesClient 类型, 封装了所有与索引库操作有关的方法.
@Test
void testExistsHotelIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("hotel");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.err.println(exists ? "索引库已经存在!" : "索引库不存在!");
}
通过上面的创建 / 删除 / 查询 操作可以看得出来, JavaRestClient 的步骤和 ElasticSearch 的流程基本相似, 核心都在 client.indices() 这个方法上, 索引库的基本步骤如下:
关于 RestClient 文档的操作也是要参照已经写好的 DSL 语句, 操作并不是很难; 但是前提是要确定好自己的数据库的实体类, 其次还要定义一个新的实体类, 这个实体类要与索引库的结构吻合 (我这里的数据还是用的某站酒店的数据).
关于文档的新增也是分为三步走, 先是创建 Request 对象, 然后准备请求的参数, 也就是 DSL 中的数据, 最后发送请求即可.
@Test
void testAddDocument() throws IOException {
Hotel hotel = hotelService.getById(1);
HotelDoc hotelDoc = new HotelDoc(hotel);
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
我们从数据库中获取到的数据需要先查询出来, 得到数据对象, 然后需要转换为 HotelDoc 对象 (因为要与索引库的结构一致), 然后再序列化为 json 格式;
具体流程步骤:
查询文档比较简单, 只需要准备 Request 对象, 然后发送请求即可; 这里还是要注意, 查询到的是 JSON 文档, 因此需要将 JSON 数据进行解析.
@Test
void testGetDocumentById() throws IOException {
GetRequest request = new GetRequest("hotel","61083");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
具体步骤:
删除文档和查询文档基本类似, 只是将 get 改成了 delete;
@Test
void testDeleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("hotel", "1");
client.delete(request, RequestOptions.DEFAULT);
}
关于文档的修改前面的文章已经说过有两种方法, 全量修改和增量修改;
@Test
void testUpdateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("hotel", "1");
request.doc(
"name", "Remake",
"age", "999"
);
client.update(request, RequestOptions.DEFAULT);
}
批量数据的导入用到了 BulkRequest, 具体步骤和新增基本一致, 先查询到数据库中的数据, 然后转换为 Doc 文档数据, 利用 BulkRequest 进行批处理, 实现批量数据的新增文档.
批量数据的新增其实质就是将多个 CRUD 请求组合在一起进行发送, 其中提供了一个 add 方法, 用来添加其他的请求, 其他的请求就包含了新增, 修改和删除操作.
@Test
void testBulkRequest() throws IOException {
List<Hotel> hotels = hotelService.list();
BulkRequest request = new BulkRequest();
for (Hotel hotel : hotels) {
HotelDoc hotelDoc = new HotelDoc(hotel);
request.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc), XContentType.JSON));
}
client.bulk(request, RequestOptions.DEFAULT);
}
具体步骤: