可以参考着“利用JavaRestClient实现文档的CRUD(从mysql数据库转移到es)”来看
http://t.csdn.cn/SP5nx
1、解析响应的方法
private void handleResponse(SearchResponse response) {
// 4.解析响应
SearchHits searchHits = response.getHits();
// 4.1.获取总条数
long total = searchHits.getTotalHits().value;
System.out.println("共搜索到" + total + "条数据");
// 4.2.文档数组
SearchHit[] hits = searchHits.getHits();
// 4.3.遍历
for (SearchHit hit : hits) {
// 获取文档source
String json = hit.getSourceAsString();
// 反序列化
//HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
//System.out.println("hotelDoc = " + hotelDoc);
System.out.println(json);
}
}
2、无条件查找
package cn.itcast.hotel;
import cn.itcast.hotel.pojo.HotelDoc;
import cn.itcast.hotel.service.IHotelService;
import cn.itcast.hotel.utils.HotelConstants;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 酒店查询测试
*
* @author ning
* @since 2022/12/5 22:45
*/
@Slf4j
@SpringBootTest
public class HotelSearchTest {
@Autowired
private IHotelService hotelService;
@Test
void testMatchAll() throws Exception {
//初始化RestHighLevelClient:
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(HttpHost.create("http://192.168.177.132:9200"))
);
//创建请求
//hotel 是查询的文档名
SearchRequest request = new SearchRequest("hotel");
//设置参数
//QueryBuilders 工具类
//matchAllQuery() 无条件查询
request.source()
.query(QueryBuilders.matchAllQuery());
//执行请求
//第一个参数:创建的请求,第二个参数:是否还有其他的选项,一般选DEFAULT
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
//解析响应
handleResponse(response);
}
private void handleResponse(SearchResponse response) {
// 4.解析响应
SearchHits searchHits = response.getHits();
// 4.1.获取总条数
long total = searchHits.getTotalHits().value;
System.out.println("共搜索到" + total + "条数据");
// 4.2.文档数组
SearchHit[] hits = searchHits.getHits();
// 4.3.遍历
for (SearchHit hit : hits) {
// 获取文档source
String json = hit.getSourceAsString();
// 反序列化
HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
System.out.println("hotelDoc = " + hotelDoc);
}
}
}
3、全文检索查询
单字段全文检索查询:match查询
代码和上边无条件查询基本一致,只是需要把查询条件换一下
//设置参数
//QueryBuilders 工具类
request.source()
.query(
//QueryBuilders.matchAllQuery() //无条件查询
QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
);
多字段全文检索查询:multi_match查询
代码和上边无条件查询基本一致,只是需要把查询条件换一下
//设置参数
//QueryBuilders 工具类
request.source()
.query(
//QueryBuilders.matchAllQuery() //无条件查询
//QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
QueryBuilders.multiMatchQuery("如家","name","brand","business")//multi_match查询(多字段全文检索查询)
);
4、精确查询
精确查询主要是两者:
term:词条精确匹配
range:范围查询
term:词条精确匹配
//设置参数
//QueryBuilders 工具类
request.source()
.query(
//QueryBuilders.matchAllQuery() //无条件查询
//QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
//QueryBuilders.multiMatchQuery("如家","name","brand","business")//multi_match查询(多字段全文检索查询)
QueryBuilders.termQuery("city","北京")//词条精确匹配
);
range:范围查询
//设置参数
//QueryBuilders 工具类
request.source()
.query(
//QueryBuilders.matchAllQuery() //无条件查询
//QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
//QueryBuilders.multiMatchQuery("如家","name","brand","business")//multi_match查询(多字段全文检索查询)
//QueryBuilders.termQuery("city","北京")//term:词条精确匹配
QueryBuilders.rangeQuery("price").gte(100).lte(200)//range:范围查询
);
5、复合查询-boolean query
布尔查询是用must、must_not、filter等方式组合其它查询,代码示例如下:
//设置参数
//QueryBuilders 工具类
request.source()
.query(
//QueryBuilders.matchAllQuery() //无条件查询
//QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
//QueryBuilders.multiMatchQuery("如家","name","brand","business")//multi_match查询(多字段全文检索查询)
//QueryBuilders.termQuery("city","北京")//term:词条精确匹配
//QueryBuilders.rangeQuery("price").gte(100).lte(200)//range:范围查询
//boolQuery 布尔查询
//其中的子查询包括酒店名字为如家,并且价格在100~200之间的
//子查询可以有多个
QueryBuilders.boolQuery()
.must(QueryBuilders.matchQuery("name", "如家"))
.filter(QueryBuilders.rangeQuery("price").gte(100).lte(200))
);
6、对查询结果进行排序和分页
计算分页的公式:(当前页-1)*每页显示多少条数据,可以得出要从哪一条数据开始查
//排序
//按照价格升序
request.source().sort("price", SortOrder.ASC);
//分页
//一般由前端返回分页的数据
int pageNo = 1;//当前页
int pageSize = 2;//每页显示多少数据
request.source().from((pageNo-1)*pageSize).size(pageSize);
7、对查询结果高亮显示
高亮的代码与之前代码差异较大,有两点:
查询的DSL:其中除了查询条件,还需要添加高亮条件,同样是与query同级。
结果解析:结果除了要解析_source文档数据,还要解析高亮结果
7.1 高亮请求构建
高亮查询必须使用全文检索查询,并且要有搜索关键字,将来才可以对关键字高亮。
//高亮的请求
//将酒店名中的如家两个字高亮显示,
//HighlightBuilder 工具类
//field 在哪个字段使用高亮显示
//requireFieldMatch 如果查询的字段和高亮显示使用的字段比一样,需要指定为false
//建议就算一样,也写上,不会有影响
request.source().highlighter(
new HighlightBuilder().field("name").requireFieldMatch(false)
);
7.3 高亮结果解析
高亮的结果与查询的文档结果默认是分离的,并不在一起。
因此解析高亮的代码需要额外处理:
代码解读:
第一步:从结果中获取source。hit.getSourceAsString(),这部分是非高亮结果,json字符串。还需要反序列为HotelDoc对象
第二步:获取高亮结果。hit.getHighlightFields(),返回值是一个Map,key是高亮字段名称,值是HighlightField对象,代表高亮值
第三步:从map中根据高亮字段名称,获取高亮字段值对象HighlightField
第四步:从HighlightField中获取Fragments,并且转为字符串。这部分就是真正的高亮字符串了
第五步:用高亮的结果替换HotelDoc中的非高亮结果
private void handleResponse(SearchResponse response) {
// 4.解析响应
SearchHits searchHits = response.getHits();
// 4.1.获取总条数
long total = searchHits.getTotalHits().value;
System.out.println("共搜索到" + total + "条数据");
// 4.2.文档数组
SearchHit[] hits = searchHits.getHits();
// 4.3.遍历
for (SearchHit hit : hits) {
// 获取文档source
String json = hit.getSourceAsString();
System.out.println(json);
反序列化
//HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
// 获取高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
if (!CollectionUtils.isEmpty(highlightFields)) {
// 根据字段名获取高亮结果
HighlightField highlightField = highlightFields.get("name");
if (highlightField != null && highlightField.getFragments().length > 0) {
// 获取高亮值
String name = highlightField.getFragments()[0].string();
覆盖非高亮结果
//hotelDoc.setName(name);
System.out.println("高亮处理后的酒店名称:" + name);
}
}
}
}