ES
官方提供了各种不同语言的客户端,用来操作ES
。这些客户端的本质就是组装DSL
语句,通过http
请求发送给ES
。官方文档地址
Demo
工程首先导入数据库数据,数据结构如下:
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;
创建项目工程,项目结构如图:
mapping
映射分析创建索引库,最关键的是mapping
映射,而mapping
映射要考虑的信息包括:
其中:
ik_max_word
来看下酒店数据的索引库结构:
PUT /hotel
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name":{
"type": "text",
"analyzer": "ik_max_word",
"copy_to": "all"
},
"address":{
"type": "keyword",
"index": false
},
"price":{
"type": "integer"
},
"score":{
"type": "integer"
},
"brand":{
"type": "keyword",
"copy_to": "all"
},
"city":{
"type": "keyword",
"copy_to": "all"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
几个特殊字段说明:
location
:地理坐标,里面包含精度、纬度all
:一个组合字段,其目的是将多字段的值 利用copy_to
合并,提供给用户搜索地理坐标说明:
copy_to
说明:
RestClient
在elasticsearch
提供的API
中,与elasticsearch
一切交互都封装在一个名为RestHighLevelClient
的类中,必须先完成这个对象的初始化,建立与elasticsearch
的连接。
分为三步:
1)引入es
的RestHighLevelClient
依赖:
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
dependency>
2)因为SpringBoot
默认的ES
版本是7.6.2
,所以我们需要覆盖默认的ES
版本:
<properties>
<java.version>1.8java.version>
<elasticsearch.version>7.10.1elasticsearch.version>
properties>
3)初始化RestHighLevelClient
:
初始化的代码如下:
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.1.111:9200")
));
这里为了单元测试方便,我们创建一个测试类HotelIndexTest
,然后将初始化的代码编写在@BeforeEach
方法中:
package com.dcxuexi.hotel;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import java.io.IOException;
/***
* @Title HotelIndexTest
* @Description TOTD
* @Auter DongChuang
* @Date 2023/4/1 17:58
* @Version 1.0.0
*/
public class HotelIndexTest {
private RestHighLevelClient client;
@BeforeEach
void setUp(){
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("192.168.1.111:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
创建索引库的API
如下:
代码分为三步:
Request
对象。因为是创建索引库的操作,因此Request
是CreateIndexRequest
。DSL
的JSON
参数部分。因为json
字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE
,让代码看起来更加优雅。client.indices()
方法的返回值是IndicesClient
类型,封装了所有与索引库操作有关的方法。在hotel-demo
的com.dcxuexi.hotel.constants
包下,创建一个类,定义mapping
映射的JSON
字符串常量:
package com.dcxuexi.hotel.constants;
/***
* @Title HotelConstants
* @Description TOTD
* @Auter DongChuang
* @Date 2023/4/1 18:07
* @Version 1.0.0
*/
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 hotelRequest = new CreateIndexRequest("hotel");
// 2.准备请求的参数:DSL语句
hotelRequest.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
// 3.发送请求
client.indices().create(hotelRequest, RequestOptions.DEFAULT);
}
删除索引库的DSL
语句非常简单:
DELETE /hotel
与创建索引库相比:
PUT
变为DELTE
所以代码的差异,注意体现在Request
对象上。依然是三步走:
Request
对象。这次是DeleteIndexRequest
对象delete
方法在hotel-demo
中的HotelIndexTest
测试类中,编写单元测试,实现删除索引:
@Test
void testDeleteHotelIndex() throws IOException{
// 1.创建Request对象
DeleteIndexRequest deleteRequest = new DeleteIndexRequest("hotel");
// 2.发送请求
client.indices().delete(deleteRequest,RequestOptions.DEFAULT);
}
判断索引库是否存在,本质就是查询,对应的DSL
是:
GET /hotel
因此与删除的Java
代码流程是类似的。依然是三步走:
Request
对象。这次是GetIndexRequest
对象exists
方法 @Test
void testExistsHotelIndex() throws IOException{
// 1.创建Request对象
GetIndexRequest getIndexRequest = new GetIndexRequest("hotel");
// 2.发送请求
boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
// 3.输出
System.out.println(exists?"索引库已经存在!":"索引库不存在!");
}
JavaRestClient
操作elasticsearch
的流程基本类似。核心是client.indices()
方法来获取索引库的操作对象。
索引库操作的基本步骤:
RestHighLevelClient
XxxIndexRequest
。XXX
是Create
、Get
、Delete
DSL
(Create
时需要,其它是无参)RestHighLevelClient#indices().xxx()
方法,xxx
是create
、exists
、delete