ES官方提供了各种不同语言的客户端,用来操作ES。这些客户端的本质就是组装DSL语句,通过http请求发送给ES。
官方文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html
资源链接
数据库数据:https://pan.baidu.com/s/1KC16E5Xpl_HsvHriGrfUkw
提取码:GY66
hotel-demo:https://pan.baidu.com/s/1MxVBdmeL4C3QhLlZrru8hA
提取码:GY66
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;
tips:
ES中支持两种地理坐标数据类型:
geo_point:由纬度(latitude)和经度(longitude)确定的一个点。
例如:"32.8752345, 120.2981576"
geo_shape:有多个geo_point组成的复杂几何图形。
例如一条直线,"LINESTRING (-77.03653 38.897676, -77.009051 38.889939)"
我们期望可以根据多个字段搜索,同时也期望搜索的效率较高(es在做搜索时只根据一个字段搜索显然效率更高)。字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段。示例:
"all": {
"type": "text",
"analyzer": "ik_max_word"
},
"brand": {
"type": "keyword",
"copy_to": "all"
}
案例:利用JavaRestClient实现创建、删除索引库,判断索引库是否存在
根据提供的酒店数据创建索引库,索引库名为hotel,mapping属性根据数据库结构定义。
1、导入Demo案例
2、分析数据结构,定义mapping属性
mapping要考虑的问题:
字段名、数据类型、是否参与搜索、是否分词、如果分词,分词器是什么?
# 酒店的mapping
```sql
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}"
},
"latitude":{
"type": "geo_point"
},
"location":{ #将经纬度拼接在一起
"type": "geo_point"
},
"pic":{
"type":"keyword",
"index": false
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
3、初始化JavaRestClient
① 引入es的RestHighLevelClient依赖:
<dependency>
<groupId>org.elasticsearch.clientgroupId>
<artifactId>elasticsearch-rest-high-level-clientartifactId>
dependency>
② 因为SpringBoot默认的ES版本是7.6.2,所以我们需要覆盖默认的ES版本
<properties>
<java.version>1.8java.version>
<elasticsearch.version>7.12.1elasticsearch.version>
properties>
③ 初始化RestHighLevelClient:
@SpringBootTest
class HotelDemoApplicationTests {
private RestHighLevelClient client;
@BeforeEach
// 初始化RestHighLevelClient
void setUp() {
this.client=new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.197.140:9200"))); // 若是集群,可指定多个
}
@Test
void testInit() {
System.out.println(client);
}
@AfterEach
// 销毁
void tearDown() throws IOException {
this.client.close();
}
}
4、利用JavaRestClient创建索引库
映射模板工具类
package com.GY.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 "+
" },\n "+
" \"starName\":{\n "+
" \"type\": \"keyword\"\n "+
" },\n "+
" \"business\":{\n "+
" \"type\":\"keyword\",\n "+
" \"copy_to\": \"{all}\"\n "+
" },\n "+
" \"latitude\":{\n "+
" \"type\": \"geo_point\"\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 "+
" } ";
}
在测试类中进行测试
@SpringBootTest
class HotelDemoApplicationTests {
private RestHighLevelClient client;
@Test
void testCreateHotelIndex() throws IOException {
// 1、 创建Request对象—————>索引库
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2、 请求参数,MAPPING_TEMPLATE是静态常量,内容是创建索引库的DSL语句(JSON文档)
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3、发送请求 indices()————>返回的对象中包含索引库操作的所有方法
client.indices().create(request, RequestOptions.DEFAULT);
}
// 初始化RestHighLevelClient
@BeforeEach
void setUp() {
this.client=new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.197.140:9200"))); // 若是集群,可指定多个
}
@AfterEach
// 销毁
void tearDown() throws IOException {
this.client.close();
}
}
5、利用JavaRestClient删除索引库
@Test
void testDeleteHotelIndex() throws IOException {
// 1、 创建Request对象
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 2、 发起请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
6、利用JavaRestClient判断索引库是否存在
@Test
void testExistsHotelIndex() throws IOException {
// 1、 创建Request对象
GetIndexRequest request=new GetIndexRequest("hotel");
// 2、 发起请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.err.print(exists ? "索引库已存在!" : "索引库不存在!");
}
索引库操作总结
索引库操作的基本步骤:
初始化RestHighLevelClient
创建XxxIndexRequest。XXX是Create、Get、Delete
准备DSL( Create时需要)
发送请求。调用RestHighLevelClient#indices().xxx()方法,xxx是create、exists、delete
案例:利用JavaRestClient实现文档的CRUD
从数据库查询酒店数据,导入到hotel索引库,实现酒店数据的CRUD。
1、初始化JavaRestClient
2、利用JavaRestClient新增酒店数据
先查询酒店数据,然后给这条数据创建倒排索引,便可完成添加
@SpringBootTest
public class ElasticSearchDocumentTest {
@Autowired
private IHotelService hotelService;
private RestHighLevelClient client;
// 新增文档
@Test
void testIndexDocument() throws IOException {
Hotel hotel = hotelService.getById(61083L);
//转换数据 (由数据库类型转化为索引库所需要的类型)
HotelDoc hoteldoc=new HotelDoc(hotel);
// 1、 创建Request对象 (需转成字符串,索引库对于id的要求都为keyword类型,因此都为字符串)
IndexRequest request=new IndexRequest("hotel").id(hotel.getId().toString());
// 2、 准备JSON文档
request.source(JSON.toJSONString(hoteldoc), XContentType.JSON);
// 3、 发送请求——————index: 创建倒排索引
client.index(request, RequestOptions.DEFAULT);
}
// 初始化RestHighLevelClient
@BeforeEach
void setUp() {
this.client=new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.197.140:9200") // 若是集群,可指定多个
//HttpHost.create("http://192.168.197.141:9200"),
//HttpHost.create("http://192.168.197.141:9200")
));
}
@AfterEach
// 销毁
void tearDown() throws IOException {
this.client.close();
}
}
3、利用JavaRestClient根据id查询酒店数据(根据id查询到的文档数据是json,需要反序列化为java对象)
// 查询文档
@Test
void testGetDocumentByID() throws IOException {
// 1、创建Request对象
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); //利用fastjson反序列化
System.err.println(hotelDoc);
}
4、利用JavaRestClient删除酒店数据
// 删除文档
@Test
void testSelectDocumentById() throws IOException {
// 1、获取request对象
DeleteRequest request=new DeleteRequest("hotel","61083");
// 2、删除文档
client.delete(request,RequestOptions.DEFAULT);
}
5、利用JavaRestClient修改酒店数据
方式一:全量更新。再次写入id一样的文档,就会删除旧文档,添加新文档
方式二:局部更新。只更新部分字段,此处为方式二
// 更新文档
@Test
void testUpdateDocumentById() throws IOException {
// 1、获取request对象
UpdateRequest request = new UpdateRequest("hotel","61083");
// 2、 准备参数,每两个参数为一对 key value
request.doc(
"age",18,
"name","GY"
);
// 3、更新文档
client.update(request,RequestOptions.DEFAULT);
}
文档操作总结
文档操作的基本步骤:
初始化RestHighLevelClient
创建XxxRequest。XXX是Index、Get、Update、Delete
准备参数(Index和Update时需要)
发送请求。调用RestHighLevelClient#.xxx()方法,xxx是index、get、update、delete
解析结果(Get时需要)
案例:利用JavaRestClient批量导入酒店数据到ES(批量查询酒店数据,然后批量导入索引库中)
1、利用mybatis-plus查询酒店数据
2、将查询到的酒店数据(Hotel)转换为文档类型数据(HotelDoc)
3、利用JavaRestClient中的Bulk批处理,实现批量新增文档,示例代码如下
// 五、批量导入文档
@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.add(new IndexRequest("hotel")
.id(hotelDoc.getId().toString())
.source(JSON.toJSONString(hotelDoc),XContentType.JSON));
}
// 3、发送请求
client.bulk(request,RequestOptions.DEFAULT);
}
批量查询:
GET /hotel/_search