ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html
其中的Java Rest Client又包括两种:
Java Low Level Rest ClientJava High Level Rest Client
这里使用的是Java HighLevel Rest Client
数据结构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;创建索引库
ES中支持两种地理坐标数据类型:
geo_point:由纬度(latitude)和经度(longitude)确定的一个点。例如:“32.8752345, 120.2981576”geo_shape:有多个geo_point组成的复杂几何图形。例如一条直线,“LINESTRING (-77.03653 38.897676, -77.009051 38.889939)”
字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段,实现根据一个字段搜索多个字段的效果。
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"
},
"starName":{
"type": "keyword"
},
"business":{
"type": "keyword",
"copy_to":"all"
},
"location":{
"type": "geo_point"
},
"pic":{
"type": "keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
几个特殊字段说明:
location:地理坐标,里面包含精度、纬度all:一个组合字段,其目的是将多字段的值 利用copy_to合并,提供给用户搜索 初始化RestClient
在elasticsearch提供的API中,与elasticsearch一切交互都封装在一个名为RestHighLevelClient的类中,必须先完成这个对象的初始化,建立与elasticsearch的连接。
引入es的RestHighLevelClient依赖覆盖默认的ES版本org.elasticsearch.client elasticsearch-rest-high-level-client
因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本
初始化RestHighLevelClient1.8 7.12.1
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.116.131:9200")
));
单元测试
创建一个测试类HotelIndexTest,然后将初始化的代码编写在@BeforeEach方法中:
public class HotelIndexTest {
private RestHighLevelClient client;
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.116.131:9200")
));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
创建索引库
代码解读
代码分为三步:
1)创建Request对象。因为是创建索引库的操作,因此Request是CreateIndexRequest。2)添加请求参数,其实就是DSL的JSON参数部分。因为json字符串很长,这里是定义了静态字符串常量MAPPING_TEMPLATE,让代码看起来更加优雅。3)发送请求,client.indices()方法的返回值是IndicesClient类型,封装了所有与索引库操作有关的方法。 定义mapping映射的JSON字符串常量
package cn.bttc.hotel.constants;
public class HotelIndexConstants {
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": falsen" +
" },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" +
" "pic": {n" +
" "type": "keyword",n" +
" "index": falsen" +
" },n" +
" "location": {n" +
" "type": "geo_point"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.准备请求的参数:DSL语句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3.发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
删除索引库
@Test
void testDeleteHotelIndex() throws IOException {
// 1.创建Request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
判断索引库是否存在
@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 ? "索引库已经存在!" : "索引库不存在!");
}



