操作 - RestClinet(弃用)
注意
- 此依赖已被官方启用,转用 https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/_getting_started.html
- Elasticsearch 版本最高支持到 7
# 初始化 JavaRestClient
引入 es 的 RestHighLevelClient 依赖
<!-- elasticsearch -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.1</version>
</dependency>
因为 SpringBoot 默认的 ES 版本是 7.6.2,所以我们需要覆盖默认的 ES 版本
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
初始化 RestHighLevelClient
private RestHighLevelClient client;
/**
* 初始化
*/
@BeforeEach
public void init() {
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://10.10.10.77:9200"))
);
}
# 索引库
# 创建
@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);
}
MAPPING_TEMPLATE 为请求的 JSON 字符串
# 删除
/**
* 判断索引库是否存在.
*/
@Test
void isExistsHotelIndex() throws IOException {
// 1.创建Request对象
boolean exists = client.indices().exists(new GetIndexRequest("hotel"), RequestOptions.DEFAULT);
System.out.println(exists);
}
# 判断是否存在
/**
* 判断索引库是否存在.
*/
@Test
void isExistsHotelIndex() throws IOException {
// 1.创建Request对象
boolean exists = client.indices().exists(new GetIndexRequest("hotel"), RequestOptions.DEFAULT);
System.out.println(exists);
}
# 文档
# 创建
/**
* 创建文档,通过数据库
*/
@Test
public void createDocument() throws IOException {
Hotel hotel = hotelService.getById(61083L);
// 转换为文档类型
HotelDoc hotelDoc = new HotelDoc(hotel);
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
request.source(JSON.toJSONString(hotelDoc), XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
# 批量创建
/**
* 批量新增文档
*/
@Test
public void bulkDocument() throws IOException {
// 获取所有酒店
List<Hotel> hotelList = hotelService.list();
// 准备请求
BulkRequest request = new BulkRequest();
// 转换为文档类型
for (Hotel hotel : hotelList) {
HotelDoc hotelDoc = new HotelDoc(hotel);
// 准备请求,添加多个request
request.add(new IndexRequest("hotel").id(hotel.getId().toString())
.source(JSON.toJSONString(hotelDoc), XContentType.JSON));
}
// 发送请求
client.bulk(request, RequestOptions.DEFAULT);
}
# 查询
/**
* 查询文档
* @throws IOException
*/
@Test
public void getDocument() throws IOException {
// 准备请求
// 发送请求
GetRequest request = new GetRequest("hotel", "61083");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 解析响应
String json = response.getSourceAsString();
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println(hotelDoc);
}
# 修改
/**
* 修改文档
* @throws IOException
*/
@Test
public void updateDocument() throws IOException {
// 准备请求
UpdateRequest request = new UpdateRequest("hotel", "61083");
// 准备请求参数
request.doc(
"price", "952",
"starName", "四钻"
);
// 发送请求
client.update(request, RequestOptions.DEFAULT);
}
# 删除
/**
* 删除文档
* @throws IOException
*/
@Test
public void deleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("hotel", "61083");
client.delete(request, RequestOptions.DEFAULT);
}
# 文档 - 搜索(列表查询)
@Test
void testMatchAll() throws IOException {
// 创建一个请求
SearchRequest request = new SearchRequest("hotel");
// 设置查询条件
request.source().query(
// 匹配所有
QueryBuilders.matchAllQuery()
);
// 执行请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
// 解析响应
SearchHits hits = response.getHits();
// 获取总记录数
long total = hits.getTotalHits().value;
System.out.println("总记录数:" + total);
// 获取每条记录
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// 获取每条记录的_source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
// 输出
System.out.println(hotelDoc);
}
System.out.println(response);
}
RestAPI 中其中构建 DSL 是通过 HighLevelRestClient
中的 resource()
来实现的,其中包含了查询、排序、分页、高亮等所有功能:
RestAPI 中其中构建查询条件的核心部分是由一个名为 QueryBuilders
的工具类提供的,其中包含了各种查询方法:
查询的基本步骤是:
- 创建 SearchRequest 对象
- 准备 Request.source (),也就是 DSL。
- QueryBuilders 来构建查询条件
- 传入 Request.source () 的 query () 方法
- 发送请求,得到结果
- 解析结果(参考 JSON 结果,从外到内,逐层解析)
# 全文检索查询
全文检索的 match 和 multi_match 查询与 match_all 的 API 基本一致。差别是查询条件,也就是 query 的部分。 同样是利用 QueryBuilders 提供的方法:
// 单字段查询
QueryBuilders.matchQuery("all", "如家");
// 多字段查询
QueryBuilders.multiMatchQuery("如家", "name", "business");
对应
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
}
}
GET /hotel/_search
{
"query": {
"multi_match": {
"query": "如家",
"fields": ["brand", "name"]
}
}
}
Example:
点击查看
@Test
void testMatch() throws IOException {
// 创建一个请求
SearchRequest request = new SearchRequest("hotel");
// 设置查询条件
request.source().query(
QueryBuilders.matchQuery("all", "如家")
);
// 执行请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
# 精确查询
// 词条查询
QueryBuilders.termQuery("city", "杭州");
// 范围查询
QueryBuilders.rangeQuery("price").gte(100).lte(150);
对应
GET /hotel/_search
{
"query": {
"term": {
"city": "杭州"
}
}
}
GET /hotel/_search
{
"query": {
"range": {
"price": { "gte": 100, "lte": 150 }
}
}
}
# 复合查询 - boolean query
精确查询常见的有 term 查询和 range 查询,同样利用 QueryBuilders 实现:
// 创建布尔查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
// 添加must条件
boolQuery.must(QueryBuilders.termQuery("city", "杭州"));
// 添加filter条件
boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"term": { "city": "杭州" }
}
],
"filter": [
{
"range": {
"price": { "lte": 250 }
}
}
]
}
}
}
Example:
点击查看
@Test
void testBool() throws IOException {
// 创建一个请求
SearchRequest request = new SearchRequest("hotel");
// 设置查询条件
request.source().query(
QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery("city", "杭州"))
.filter(QueryBuilders.rangeQuery("price").lte(250))
);
// 执行请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
# 组合查询 - function score
# 排序和分页
搜索结果的排序和分页是与 query 同级的参数,对应的 API 如下:
// 查询
request.source().query(QueryBuilders.matchAllQuery());
// 分页
request.source().from(0).size(5);
// 价格排序
request.source().sort("price", SortOrder.ASC);
GET /indexName/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 5,
"sort": [
{
"FIELD": "desc"
},
]
}
Example:
点击查看
@Test
void testPageAndSort() throws IOException {
int page = 2, size = 5;
// 创建一个请求
SearchRequest request = new SearchRequest("hotel");
// 设置查询条件
request.source()
.query(
QueryBuilders.matchAllQuery()
)
// 排序
.sort("price", SortOrder.ASC)
// 分页
.from((page - 1) * size).size(5)
;
// 执行请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
# 距离排序
# 高亮
高亮 API 包括请求 DSL 构建和结果解析两部分
# DSL 构建
request.source().highlighter(new HighlightBuilder()
.field("name")
// 是否需要与查询字段匹配
.requireFieldMatch(false)
);
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
},
"highlight": {
"fields": {
"name": {
"require_field_match": "false"
}
}
}
}
Example:
点击查看
@Test
void testHighlight() throws IOException {
// 创建一个请求
SearchRequest request = new SearchRequest("hotel");
// 设置查询条件
request.source()
// 查询
.query(
QueryBuilders.matchQuery("all", "如家")
)
// 高亮
.highlighter(
new HighlightBuilder()
.field("name").requireFieldMatch(false)
)
;
// 执行请求
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
handleResponse(response);
}
# 高亮结果解析
private void handleResponse(SearchResponse response) {
// 解析响应
SearchHits hits = response.getHits();
// 获取总记录数
long total = hits.getTotalHits().value;
System.out.println("总记录数:" + total);
// 获取每条记录
SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
// 获取每条记录的_source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
// 处理高亮内容 start ------------------>
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
// 根据字段名称获取高亮内容
HighlightField nameField = highlightFields.get("name");
if (Objects.nonNull(nameField)) {
// 获取高亮值
String name = nameField.getFragments()[0].string();
// 覆盖原始值
hotelDoc.setName(name);
}
}
// 处理高亮内容 end ------------------>
// 输出
System.out.println(hotelDoc);
}
System.out.println(response);
}
上次更新: 2024/03/11, 22:37:05