可以参考着“利用JavaRestClient实现文档的CRUD(从mysql数据库转移到es)”来看
- 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);
- }
- }
- 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);
- }
- }
- }


代码和上边无条件查询基本一致,只是需要把查询条件换一下
- //设置参数
- //QueryBuilders 工具类
- request.source()
- .query(
- //QueryBuilders.matchAllQuery() //无条件查询
- QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
- );


代码和上边无条件查询基本一致,只是需要把查询条件换一下
- //设置参数
- //QueryBuilders 工具类
- request.source()
- .query(
- //QueryBuilders.matchAllQuery() //无条件查询
- //QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
- QueryBuilders.multiMatchQuery("如家","name","brand","business")//multi_match查询(多字段全文检索查询)
- );



精确查询主要是两者:
term:词条精确匹配
range:范围查询
- //设置参数
- //QueryBuilders 工具类
- request.source()
- .query(
- //QueryBuilders.matchAllQuery() //无条件查询
- //QueryBuilders.matchQuery("all", "如家")//match查询(单字段全文检索查询)
- //QueryBuilders.multiMatchQuery("如家","name","brand","business")//multi_match查询(多字段全文检索查询)
- QueryBuilders.termQuery("city","北京")//词条精确匹配
- );


- //设置参数
- //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:范围查询
- );


布尔查询是用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))
- );


计算分页的公式:(当前页-1)*每页显示多少条数据,可以得出要从哪一条数据开始查
- //排序
- //按照价格升序
- request.source().sort("price", SortOrder.ASC);
- //分页
- //一般由前端返回分页的数据
- int pageNo = 1;//当前页
- int pageSize = 2;//每页显示多少数据
- request.source().from((pageNo-1)*pageSize).size(pageSize);


高亮的代码与之前代码差异较大,有两点:
查询的DSL:其中除了查询条件,还需要添加高亮条件,同样是与query同级。
结果解析:结果除了要解析_source文档数据,还要解析高亮结果
高亮查询必须使用全文检索查询,并且要有搜索关键字,将来才可以对关键字高亮。

- //高亮的请求
- //将酒店名中的如家两个字高亮显示,
- //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
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);
- }
- }
- }
- }

