使用JavaRestClient查询文档&排序、分页、高亮

本文介绍如何使用Java RestClient操作Elasticsearch实现CRUD,并详细讲解了无条件查找、全文检索、精确查询、复合查询、排序分页及高亮显示等查询方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可以参考着“利用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);
                }
            }
        }
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值