一、了解elasticsearch?
1,elasticsearch的作用
elasticsearch是一款非常强大的开源搜索引擎,具备非常多强大的功能,可以帮助我们在海量数据中快速搜索想要的内容。
同时支持分页与高亮显示。
2,ELK技术栈
elastic stack(ELK)是elasticsearch结合kibana、Logstash的技术栈。
其中,elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。
Kibana负责数据可视化,Logstash、Beats负责数据抓取
3,elasticsearch和lucene
-
lucene:
- Lucene是一个Java语言的搜索引擎类库,是Apache公司的顶级项目,由DougCutting于1999年研 发。官网地址:https://lucene.apache.org/ 。
- lucene是elasticsearch的底层。
- 优势:
- 易扩展
- 高性能(基于倒排搜索 )
- 缺点:
- 只限于java语言开发(因为他是基于java语言的类库)
- 不利于水平扩展
-
elasticsearch:
- elasticsearch是基于lucene实现的,但是它改变了lucene的缺点
- 提供Restful接口,可被任意语言调用
- 支持分布式,可水平扩展
- elasticsearch是基于lucene实现的,但是它改变了lucene的缺点
二、正向索引与倒排索引
1,正向索引
以上图为例,为表的【id】字段创建索引。
- 如果是根据【id】查询,可以直接走索引,查询速度非常快。
- 但是如果是基于【title】做模糊查询,只能逐条搜索,如上图右边。
- 逐条搜索,也就是全表搜索,一旦数据到达一定的量级(如百万条),简直就是灾难。
- 为此,出现了一种新的搜索方式,倒排索引。
即便为title建立索引,数据库模糊匹配,索引不生效。
2,倒排搜索
倒排搜索中的相关概念:
文档(
Document
):用来搜索的数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息词条(
Term
):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。 例如:小米手机充电器,就可以分为:小米、手机、充电器等
2.1,创建倒排索引
创建倒排索引是对正向索引的一种特殊处理,图示如下:
左边的表是数据库数据导入es后的索引库的文档。
创建的词条表放在es中,获取文档id后在文档中查询想要的数据。
- 如对【title】进行处理。
- 将每条文档数据利用算法分词,得到一个个词条。
- 数据库每条数据就是一个文档。
- 创建词条表,每行数据包括词条、词条所在的文档【id】、位置等信息
并将对应的数据存入词条表
- 因为词条具有唯一性,可以给词条创建索引。
创建过程:
1,将【小米手机】分为【小米、手机】
2,在词条表的词条列创建【小米】,并在文档id列填写【1】
3,在词条表的词条列创建【手机】,并在文档id列填写【1】
4,将【华为手机】分为【华为、手机】
5,在词条表的词条列创建【华为】,并在文档id列填写【1】
6,因为词条里面已经有【手机】,在该行的文档id列添加【2】,数据变成【1,2】
2.2,倒排搜索流程
-
图解:
- 虽然经过了两次搜索,但两次都带索引,所以搜索速度并不慢。
3,正向与倒排
-
正向索引是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。
-
而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程。
-
正向索引:
- 优点:
- 可以给多个字段创建索引
- 根据索引字段搜索、排序速度非常快
- 缺点:
- 根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。
倒排索引:
- 优点:
- 根据词条搜索、模糊搜索时,速度非常快
- 缺点:
- 只能给词条创建索引,而不是字段
- 无法根据字段做排序
- 优点:
三、ES相关概念
在elasticsearch7以后,type已经没有了。
1,文档与字段
elasticsearch是面向**文档(Document)**存储的,一个文档中可以包含多个字段。
2,索引与映射
- 相同类型放在一起就是索引,类似于数据库的表。
- 映射类似于数据库表的约束信息,如字段唯一,类型为varcher等
3,mysql与elasticsearch
mysql与elasticsearch的概念做一下对比:
MySQL | Elasticsearch | 说明 |
---|---|---|
Table | Index | 索引(index),就是文档的集合,类似数据库的表(table) |
Row | Document | 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式 |
Column | Field | 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column) |
Schema | Mapping | Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema) |
SQL | DSL | DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD |
两者各自有自己的擅长支出:
-
Mysql:擅长事务类型操作,可以确保数据的安全和一致性
-
Elasticsearch:擅长海量数据的搜索、分析、计算
所以一般而言,MySQL于ES配合使用,写操作时使用MySQL,读操作时使用ES。
二者之间通过一定的方式实现数据同步。
四、安装elasticsearch,Kibana,ik分词器
单独文档。
五、索引库操作
1,概述
索引库顾名思义就是存储文档的仓库,类似于数据库的表。
只不过数据库的表存储的是一行行数据,索引库存储的是一个个文档。
2,mappings
- mappings:映射,相当于数据库表对字段的约束条件。
- type:字段数据类型,常见的简单类型有:
- 字符串:text(可分词的文本)、keyword(精确值,例如:品牌、国家、ip地址)
- 数值:long、integer、short、byte、double、float、
- 布尔:boolean
- 日期:date
- 对象:object
- index:是否创建索引,默认为true
- analyzer:使用哪种分词器
- properties:该字段的子字段
- store:是否存储
- type:字段数据类型,常见的简单类型有:
text类型需要分词,keyword类型不需要分词。
index、store默认值为true
- 见下面的例子
{
"age": 21,
"weight": 52.1,
"isMarried": false,
"info": "黑马程序员Java讲师",
"email": "zy@itcast.cn",
"score": [99.1, 99.5, 98.9],
"name": {
"firstName": "云",
"lastName": "赵"
}
}
对应的每个字段映射(mapping):
- age:类型为 integer;参与搜索,因此需要index为true;无需分词器
- weight:类型为float;参与搜索,因此需要index为true;无需分词器
- isMarried:类型为boolean;参与搜索,因此需要index为true;无需分词器
- info:类型为字符串,需要分词,因此是text;参与搜索,因此需要index为true;分词器可以用ik_smart
- email:类型为字符串,但是不需要分词,因此是keyword;不参与搜索,因此需要index为false;无需分词器
- score:虽然是数组,但是我们只看元素的类型,类型为float;参与搜索,因此需要index为true;无需分词器
- name:类型为object,需要定义多个子属性
- name.firstName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器
- name.lastName;类型为字符串,但是不需要分词,因此是keyword;参与搜索,因此需要index为true;无需分词器
3,创建索引库
# 模板
put /【索引库名称】
{
"mappings": {
"properties": {
"【字段名】":{
"【类型】": "text",
"【分词类型】": "ik_smart",
......
},
"【字段名】":{
......
},
......
}
#创建索引库
PUT /heima
{
"mappings": {
"properties": {
"info":{
"type": "text",
"analyzer": "ik_smart",
"index": true,
"store": true
},
"email":{
"type": "text",
"analyzer": "ik_max_word"
},
"brand":{
"type": "keyword"
},
"name":{
"properties": {
"firstName":{
"type":"keyword"
},
"lastName":{
"type":"keyword"
}
}
},
"birth":{
"type": "date",
"format": "yyyy-MM-dd"
}
}
}
}
4,修改索引库
索引库的修改只能增加字段
# 模板
PUT /【索引名】/_mapping
{
"properties": {
"新字段名":{
"":""
}
}
}
5,查询索引库
# 模板
GET /【索引库名】
# 查询索引
GET /heima
6,删除索引库
#模板
DELETE /【索引库名】
#删除索引
DELETE /heima
六、文档操作
1,增加文档
# 模板
POST /【索引库名】/_doc/【文档id,建议自定义,不定义会自动生成】
# 增加文档
POST /heima/_doc/1
{
"birth":"1999-10-01",
"brand":"星辰",
"email":"yuming@xc.cn",
"info":"太阳,月亮,都是星辰",
"name":{
"firstName":"鱼",
"lastName":"星辰"
}
}
2,查看文档
#模板
GET /【索引库名】/_doc/【文档id】
#查看文档
GET /heima/_doc/1
3,修改文档
#修改文档_增量修改(局部修改)
POST /heima/_update/1
{
"doc": {
"brand":"星辰",
"email":"yuming@xcy.cn"
}
}
#修改文档_全局修改
PUT /heima/_doc/1
{
"birth":"1999-10-01",
"brand":"星辰啊",
"email":"yuming@xc.cn",
"info":"太阳,月亮,都是星辰",
"name":{
"firstName":"鱼",
"lastName":"星辰"
}
}
4,删除文档
# 删除文档
# DELETE /索引名【自己创建的索引的名称】/_doc【表示操作的是文档】/1【文档id,表示存在id为1的文档】
DELETE /heima/_doc/1
七、使用java操作elasticsearch
1,准备工作
-
导入依赖
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>
-
修改上面依赖的版本
因为依赖需要于elasticsearch版本相同,elasticsearch、kibana的版本也要一样
<properties> <elasticsearch.version>7.12.1</elasticsearch.version> </properties>
-
在配置类配置RestHighLevelClient
- EsConstant.HOST【elasticsearch的ip(“192.168.138.100”)】
- EsConstant.PORT【elasticsearch的端口(9200)】
@Configuration public class EsConfig { @Bean public RestHighLevelClient restHighLevelClient(){ return new RestHighLevelClient( RestClient.builder(new HttpHost(EsConstant.HOST, EsConstant.PORT)) ); } }
2,创建索引库
创建索引库需要索引库的名称,以及索引库的样式。
// 索引库的名称
public static final String HOTEL_INDEX = "hotel";
// 索引库的样式
public static final String SOURCE = "{\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\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"all\"\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\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\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" +
"}";
-
注意
-
使用source导入索引库的样式包括索引库的大括号
-
使用mapping的话只需要mappings后面 {} 里内容,包括{}
-
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 创建索引库
*/
@Test
public void createTest() throws IOException {
CreateIndexRequest createIndexRequest =
new CreateIndexRequest(EsConstant.HOTEL_INDEX);
// 如果使用mapping,EsConstant.SOURCE只需要
createIndexRequest.source(EsConstant.SOURCE, XContentType.JSON);
restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
}
3,查询索引库
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 查询索引库
*/
@Test
public void getTest() throws IOException {
// EsConstant.HOTEL_INDEX 索引库名称
GetIndexRequest getIndexRequest = new GetIndexRequest(EsConstant.HOTEL_INDEX);
GetIndexResponse response = restHighLevelClient
.indices()
.get(getIndexRequest, RequestOptions.DEFAULT);
Collection<MappingMetadata> values = response.getMappings().values();
}
4,判断索引库是否存在
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 判断索引库算法存在
*/
@Test
public void existTest() throws IOException {
// EsConstant.HOTEL_INDEX 索引库名称
GetIndexRequest getIndexRequest = new GetIndexRequest(EsConstant.HOTEL_INDEX);
boolean exists = restHighLevelClient
.indices()
.exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
5,删除索引库
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 删除索引库
*/
@Test
public void deleteTest() throws IOException {
// EsConstant.HOTEL_INDEX 被删除的索引库名称
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(EsConstant.HOTEL_INDEX);
AcknowledgedResponse response = restHighLevelClient
.indices()
.delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println("response.isAcknowledged() = " + response.isAcknowledged());
}
6,完整代码
package cn.itcast.hotel;
import cn.itcast.hotel.constant.EsConstant;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.MappingMetadata;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.Collection;
/**
* @author 星辰鱼
* @version 1.0
* @date 2023/5/19 16:05
*/
@SpringBootTest
public class TestHotel {
@Autowired
private RestHighLevelClient restHighLevelClient;
/**
* 判断索引库算法存在
*/
@Test
public void existTest() throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest(EsConstant.HOTEL_INDEX);
boolean exists = restHighLevelClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
System.out.println(exists);
}
/**
* 查询索引库
*/
@Test
public void getTest() throws IOException {
GetIndexRequest getIndexRequest = new GetIndexRequest(EsConstant.HOTEL_INDEX);
GetIndexResponse response = restHighLevelClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
Collection<MappingMetadata> values = response.getMappings().values();
System.out.println(values);
}
/**
* 创建索引库
*/
@Test
public void createTest() throws IOException {
CreateIndexRequest createIndexRequest = new CreateIndexRequest(EsConstant.HOTEL_INDEX);
// 如果使用mapping,EsConstant.SOURCE只需要
createIndexRequest.source(EsConstant.SOURCE, XContentType.JSON);
restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
}
/**
* 删除索引库
*/
@Test
public void deleteTest() throws IOException {
// EsConstant.HOTEL_INDEX:被删除的索引库名称
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(EsConstant.HOTEL_INDEX);
AcknowledgedResponse response = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println("response.isAcknowledged() = " + response.isAcknowledged());
}
}
八、使用java操作文档
1,增加文档
- 增加文档需要 索引库名、文档id、文档内容(json格式)
/**
* 增加文档
*/
@Test
public void addDocTest() throws IOException {
// EsConstant.HOTEL_INDEX 索引库名
IndexRequest indexRequest = new IndexRequest(EsConstant.HOTEL_INDEX);
// 从数据库获取文档
Hotel hotel = hotelService.getById(36934L);
HotelDoc hotelDoc = new HotelDoc(hotel);
String jsonHotel = JSON.toJSONString(hotelDoc);
// 设置文档id
indexRequest.id(hotel.getId().toString());
// 设置文档数据
indexRequest.source(jsonHotel, XContentType.JSON);
IndexResponse response = restHighLevelClient
.index(indexRequest, RequestOptions.DEFAULT);
}
2,查询文档
- 查询文档需要 索引库名、文档id
/**
* 查询文档
*/
@Test
public void getDocTest() throws IOException {
// id是字符串形式,所以不用带L
GetRequest getRequest = new GetRequest(EsConstant.HOTEL_INDEX, "36934");
// response 中"_source"包含对象数据
GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
String source = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);
System.out.println("hotelDoc = " + hotelDoc);
}
3,修改文档
- 修改文档需要 索引库名、文档id、修改的内容
/**
* 修改文档1
*/
@Test
public void updateDocTest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest(EsConstant.HOTEL_INDEX, "36934");
// 修改文档 - 局部修改
updateRequest.doc(
XContentType.JSON,
// 依次代表 key、value,
// 表示address的值改为"新的,第三次","city"的值改为 "新的城市!第二次"
"address", "新的,第三次",
"city", "新的城市!第二次"
);
UpdateResponse response = restHighLevelClient
.update(updateRequest, RequestOptions.DEFAULT);
}
/**
* 修改文档2
*/
@Test
public void updateDocTest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest(EsConstant.HOTEL_INDEX, "36934");
// 修改文档 - 全局修改
Hotel hotel = hotelService.getById(36934L);
hotel.setAddress("新的!");
hotel.setCity("新的城市!");
String source = JSON.toJSONString(hotel);
updateRequest.doc(source, XContentType.JSON);
UpdateResponse response = restHighLevelClient
.update(updateRequest, RequestOptions.DEFAULT);
}
/**
* 修改文档3
*/
@Test
public void updateDocTest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest(EsConstant.HOTEL_INDEX, "36934");
// 修改文档 - 局部修改
HashMap<String, Object> map = new HashMap<>();
map.put("address", "新的,第二次");
updateRequest.doc(map);
UpdateResponse response = restHighLevelClient
.update(updateRequest, RequestOptions.DEFAULT);
}
4,删除文档
- 删除文档需要 索引库名、文档id
/**
* 删除文档
*/
@Test
public void deleteDocTest() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest(EsConstant.HOTEL_INDEX, "36934");
restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
}
5,完整代码,包含批量操作
package cn.itcast.hotel;
import cn.itcast.hotel.constant.EsConstant;
import cn.itcast.hotel.pojo.Hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import com.alibaba.fastjson.JSON;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
/**
* @author 星辰鱼
* @version 1.0
* @date 2023/5/19 16:44
*/
@SpringBootTest
@SuppressWarnings("all")
public class TestDoc {
@Autowired
public RestHighLevelClient restHighLevelClient;
@Autowired
public IHotelService hotelService;
/**
* 批量修改
*/
@Test
public void updateBulkTest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
// 获取数据库数据
List<Hotel> hotelList = hotelService.list();
hotelList.stream().forEach(hotel -> {
UpdateRequest updateRequest = new UpdateRequest(EsConstant.HOTEL_INDEX, hotel.getId().toString());
HashMap<String, Object> map = new HashMap<>();
map.put("address", "新的地址,第二");
UpdateRequest request = updateRequest.doc(map);
bulkRequest.add(request);
});
restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
}
/**
* 批量删除
*/
@Test
public void getBulkTest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
//获取数据库所有数据
List<Hotel> hotelList = hotelService.list();
hotelList.stream().forEach(hotel -> {
bulkRequest.add(new DeleteRequest(
EsConstant.HOTEL_INDEX)
.id(hotel.getId().toString()));
});
restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
}
/**
* 批量插入
*/
@Test
public void bulkDocTest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
// 获取数据库所以数据
List<Hotel> hotelList = hotelService.list();
hotelList.stream().forEach(hotel -> {
HotelDoc hotelDoc = new HotelDoc(hotel);
// 将hotelDoc转为json格式
String source = JSON.toJSONString(hotelDoc);
bulkRequest.add(
new IndexRequest(EsConstant.HOTEL_INDEX)
.id(hotel.getId().toString())
.source(source, XContentType.JSON)
);
});
restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
}
/**
* 删除文档
*/
@Test
public void deleteDocTest() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest(EsConstant.HOTEL_INDEX, "36934");
restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
}
/**
* 修改文档
*/
@Test
public void updateDocTest() throws IOException {
UpdateRequest updateRequest = new UpdateRequest(EsConstant.HOTEL_INDEX, "36934");
/**
* 修改文档 - 全局修改
* Hotel hotel = hotelService.getById(36934L);
* hotel.setAddress("新的!");
* hotel.setCity("新的城市!");
* String source = JSON.toJSONString(hotel);
*
* updateRequest.doc(source, XContentType.JSON);
*/
/**
* 修改文档 - 局部修改1
* HashMap<String, Object> map = new HashMap<>();
* map.put("address", "新的,第二次");
* updateRequest.doc(map);
*/
// 修改文档 - 局部修改2
updateRequest.doc(XContentType.JSON, "address", "新的,第三次", "city", "新的城市!第二次");
UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
}
/**
* 查询文档
*/
@Test
public void getDocTest() throws IOException {
// id是字符串形式,所以不用带L
GetRequest getRequest = new GetRequest(EsConstant.HOTEL_INDEX, "36934");
// response 中"_source"包含对象数据
GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
String source = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(source, HotelDoc.class);
System.out.println("hotelDoc = " + hotelDoc);
}
/**
* 增加文档
*/
@Test
public void addDocTest() throws IOException {
IndexRequest indexRequest = new IndexRequest(EsConstant.HOTEL_INDEX);
// 从数据库获取文档
Hotel hotel = hotelService.getById(36934L);
HotelDoc hotelDoc = new HotelDoc(hotel);
String jsonHotel = JSON.toJSONString(hotelDoc);
// 设置文档id
indexRequest.id(hotel.getId().toString());
// 设置文档数据
indexRequest.source(jsonHotel, XContentType.JSON);
IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
}
}