前言:
Elasticsearch是一个开源的分布式搜索和分析引擎,它提供了一个基于HTTP协议的RESTful API,用于与Elasticsearch集群进行交互。
本文主要介绍了Elasticsearch Java High-Level REST Client 来操作 Elasticsearch。该客户端封装了底层的 RESTful API,并提供了更简单和方便的接口,以进行索引、搜索、聚合等操作。
简介:RestClient是Elasticsearch Java客户端库的一部分,它提供了一种低级别的方式来与Elasticsearch集群进行通信。它是一个轻量级的HTTP客户端,用于发送请求和接收响应。
通过RestClient,我们可以直接发送HTTP请求(如GET、POST、PUT、DELETE等)到Elasticsearch集群的RESTful API端点,并处理响应数据。它提供了一些方便的方法和功能,用于执行索引、搜索、聚合、更新、删除等操作。
官方文档:
链接: https://www.elastic.co/guide/en/elasticsearch/client/index.html
通过案例形式讲解JavaRestClient创建、删除索引库,判断索引库是否存在
需要的文件:链接: https://pan.baidu.com/s/1kiFjO_Vqyl6-xJcDXrY8Xg?pwd=x1e7
提取码:x1e7
tb_hotel.sql分析:
将sql文件导入到数据库:
根据数据库表设计定义mapping属性:
定义mapping时候我们要考虑的问题:
字段名、数据类型、是否参与搜索、是否分词、分词器是什么?
这段代码是用于创建名为"hotel"的索引,并定义了该索引的映射(mapping)。在Elasticsearch中,索引是用于组织和存储文档的地方,而映射定义了文档中的字段及其属性。
PUT /hotel
{
"mappings" : {
"properties" : {
"address" : {
"type" : "keyword",
"index" : false
},
"all" : {
"type" : "text",
"analyzer" : "ik_max_word"
},
"brand" : {
"type" : "keyword",
"copy_to" : [
"all"
]
},
"business" : {
"type" : "keyword",
"copy_to" : [
"all"
]
},
"city" : {
"type" : "keyword"
},
"id" : {
"type" : "keyword"
},
"location" : {
"type" : "geo_point"
},
"name" : {
"type" : "text",
"copy_to" : [
"all"
],
"analyzer" : "ik_max_word"
},
"pic" : {
"type" : "keyword",
"index" : false
},
"price" : {
"type" : "integer"
},
"score" : {
"type" : "integer"
},
"starName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"startName" : {
"type" : "keyword"
}
}
}
}
现在对其中其中内容进行解释
“PUT /hotel”: 这是一个PUT请求,用于创建或更新名为"hotel"的索引。通过发送此请求到Elasticsearch的特定端点,可以执行相应的操作。
“mappings”: 这是一个映射定义的部分,用于指定索引中文档的字段和属性。
“properties”: 它是映射的根节点,表示文档的属性集合。
“address”: 定义了一个名为"address"的字段,其类型为"keyword",并设置了"index"为false。这表示"address"字段的内容将不会进行分词,以精确匹配方式进行索引。
“all”: 定义了一个名为"all"的字段,其类型为"text",并使用"ik_max_word"分析器。该字段用于全文搜索,将"brand"、"business"和"name"字段的内容复制到"all"字段中,以便进行全文检索。
“brand”, “business”, “city”, “id”, “location”, “name”, “pic”, “price”, “score”, “starName”, “startName”: 这些是其他字段的定义,指定了它们的类型、属性和分析器(如果适用)。
“location”: 定义了一个名为"location"的字段,其类型为"geo_point",用于存储地理位置数据。
“fields”: 在"starName"字段中,使用了一个额外的子属性"fields",其中定义了一个名为"keyword"的字段。这是为了支持同时进行全文搜索和精确匹配,其中"starName.keyword"字段将被用于精确匹配。
创建Sprinboot项目:
springboot版本:2.7.12、es版本:7.12.1、mysql版本:8.0.31
导入项目,这里我们以黑马旅游demo项目为例:
链接: https://pan.baidu.com/s/17mPIg3NKkNjhJcL0-4-jUg?pwd=h0b8
提取码:h0b8
引入依赖文件
声明Elasticsearch REST High-Level Client库的依赖,该库是用于Elasticsearch的Java客户端库。
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
dependency>
spring boot默认的版本是7.6.2我们需要覆盖版本,
<properties>
<java.version>1.8java.version>
<elasticsearch.version>7.12.1elasticsearch.version>
properties>
初始化操作:
我们在项目中添加单元测试,将RestClient初始化操作:
public class HotelIndexTest {
private RestHighLevelClient client;
/**
* @Description: setUp 初始化客户端
* @Param: * @param
* @return: void
* @Author: [email protected]
* @Date: 17:25 2023/4/9
*/
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.75.135:9200")
// HttpHost.create("http://192.168.75.133:5601"), #可指定多个
// HttpHost.create("http://192.168.75.133:5601")
));
}
//销毁客户端
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
@Test
void testInit() {
System.out.println(client);
}
}
之前我们在Kibana中创建使用的PUT命令,现在我们直接使用java的api创建索引库
我们还是使用以下代码创建:
{
"mappings" : {
"properties" : {
"address" : {
"type" : "keyword",
"index" : false
},
"all" : {
"type" : "text",
"analyzer" : "ik_max_word"
},
"brand" : {
"type" : "keyword",
"copy_to" : [
"all"
]
},
"business" : {
"type" : "keyword",
"copy_to" : [
"all"
]
},
"city" : {
"type" : "keyword"
},
"id" : {
"type" : "keyword"
},
"location" : {
"type" : "geo_point"
},
"name" : {
"type" : "text",
"copy_to" : [
"all"
],
"analyzer" : "ik_max_word"
},
"pic" : {
"type" : "keyword",
"index" : false
},
"price" : {
"type" : "integer"
},
"score" : {
"type" : "integer"
},
"starName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"startName" : {
"type" : "keyword"
}
}
}
}
首先我们需要创建一个常量用于保存DSL语句
新建包:constants、新建类HotelContants
public class HotelConstants {
public static final String MappingTemplate = "{\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" +
" },\n" +
" \"startName\": {\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" +
"}";
}
在单元测试类中加入代码:这段代码用于创建索引库的操作
@Test
void createHotelIndex() throws IOException {
//1.创建request对象
CreateIndexRequest request = new CreateIndexRequest("hotel");
//2.准备请求的参数(执行的json语句,指定类型是json类型)
request.source(HotelConstants.MappingTemplate, XContentType.JSON);
//3.发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
/**
* @Description: testDeleteHotelIndex 删除索引库对象
* @Param: * @param
* @return: void
* @Author: [email protected]
* @Date: 21:24 2023/4/10
*/
@Test
void testDeleteHotelIndex() throws IOException {
//1.创建request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
//3.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
/**
* @Description: testExistsHotelIndex 判断索引库是否存在
* @Param: * @param
* @return: void
* @Author: [email protected]
* @Date: 21:25 2023/4/10
*/
@Test
void testExistsHotelIndex() throws IOException {
//1.创建request对象
GetIndexRequest request = new GetIndexRequest("hotel");
//3.发送请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists ? "索引库已经存在":"索引库不存在");
}
建立单元测试类,然后我们直接进行初始化客户端操作,然后再进行新增文档操作
private RestHighLevelClient client;
@Autowired
private IHotelService hotelService;
/**
* @Description: setUp 初始化客户端
* @Param: * @param
* @return: void
* @Author: [email protected]
* @Date: 17:25 2023/4/9
*/
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.75.135:9200")
// HttpHost.create("http://192.168.75.133:5601"), #可指定多个
// HttpHost.create("http://192.168.75.133:5601")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
@Test
void testAddDocument() throws IOException {
//根据id查询数据
Hotel hotel = hotelService.getById(61083L);
HotelDoc hotelDoc = new HotelDoc(hotel);
//1.准备Resquest对象
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
//2.准备Json文档,先将hotelDoc对象序列化为Json类型
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
//3.发送请求
client.index(request, RequestOptions.DEFAULT);
}
在上述代码中我们先从数据库中拿到一个Hotel对象,将其id设置为HotelDoc类型,再将其转换为json类型,最终存入es的索引库"hotel"中
获取指定索引库的文档数据:
@Test
void testGetDocumentById() throws IOException {
//1.准备Request 获取指定数据请求名称是GetRequest参数是: 索引库名,文档id
GetRequest request = new GetRequest("hotel", "61083");
//2.发送请求
GetResponse response = client.get(request, RequestOptions.DEFAULT);
//3.解析响应结果
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
上述代码我们通过GetRequest获取指定索引库的指定文档,通过文档id获取指定文档。
@Test
void testUpdateDocumentById() throws IOException {
//1.创建request对象这是更新文档的对象
UpdateRequest request = new UpdateRequest("hotel","61083");
//2.准备参数
request.doc(
"price","952",
"starName","四钻"
);
//3.执行更新文档操作
client.update(request,RequestOptions.DEFAULT);
}
@Test
void testDeleteDocumentById() throws IOException {
//1.创建删除文档更新请求
DeleteRequest request = new DeleteRequest("hotel", "61083");
//2.执行删除操作
DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
System.out.println(delete);
}
通过DeleteRequest 删除指定索引库的指定文档id的文档。
@Test
void testBulkRequest() throws IOException {
//批量查询数据
List<Hotel> hotels = hotelService.list();
//1.创建Request
BulkRequest request = new BulkRequest();
//2.准备参数,添加多个Request对象
for (Hotel hotel : hotels) {
//转换为文档类型
HotelDoc hotelDoc = new HotelDoc(hotel);
//创建新增文档的request对象
request.add(new IndexRequest("hotel").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));
}
//3.发送请求
client.bulk(request, RequestOptions.DEFAULT);
}