前面我们已经实现利用DSL实现文档查询和后续结果处理,下面我们利用Java  RestClient实现前面的功能

一、快速入门

1.1.基本案例演示

我们通过match_all来演示下基本的APl,先看请求DSL的组织:查询所有的信息如下:

@SpringBootTest
public class HotelSearchTests {
    //创建成员变量,保存初始化的对象
    private RestHighLevelClient client;


    @BeforeEach
    void setUp(){
        this.client = new RestHighLevelClient(
                RestClient.builder(HttpHost.create("http://192.168.42.150:9200")
                ));
    }

    @AfterEach
    void testDown() throws IOException {
        this.client.close();
    }

    /**
     * 查询所有的数据
     * @throws IOException
     */
    @Test
    void testMatchAll() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        System.out.println(response);
    }
}

执行后结果如下:

RestClient查询文档_System

1.2.结果解析

上面的操作完成后,我们需要对于返回的结果进行解析,通过解析拿出我们需要的信息:

RestClient查询文档_Test_02

代码如下:

/**
     * 查询所有的数据
     * @throws IOException
     */
    @Test
    void testMatchAll() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        SearchHits searchHits = response.getHits();
        //4.1.查询总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到:"+total+"条数据");
        //4.2.查询的结果数组
        for (SearchHit hit : searchHits.getHits()) {
            //4.3.获取文档source
            String json = hit.getSourceAsString();
            //4.4.打印输出
            System.out.println(json);
            //4.5.反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = "+hotelDoc);
        }
    }

执行后结果如下:

RestClient查询文档_字段_03

1.3.Query Builders的工具类

Rest API中其中构建查询条件的核心部分是由一个名为Query Builders的工具类提供的,其中包含了各种查询方法:

RestClient查询文档_System_04

在 Elasticsearch Java 客户端中,Query Builders 提供了一系列用于构建查询的工具类。这些工具类通常位于 org.elasticsearch.index.query 包中。以下是一些常用的 Query Builders 工具类及其方法:

  1. QueryBuilders.termQuery(String name, Object value):创建一个精确匹配的项查询。
  2. QueryBuilders.matchQuery(String name, Object value):创建一个全文匹配查询。
  3. QueryBuilders.boolQuery():创建一个布尔查询,用于组合多个查询条件。
  4. QueryBuilders.rangeQuery(String name):创建一个范围查询,用于匹配指定范围内的值。
  5. QueryBuilders.existsQuery(String name):创建一个存在性查询,用于匹配指定字段存在的文档。
  6. QueryBuilders.prefixQuery(String name, String prefix):创建一个前缀查询,用于匹配指定前缀的项。

这些方法通常用于构建查询条件,并且可以与其他查询条件组合使用。在使用这些方法时,通常需要将返回的查询对象添加到查询构建器中,然后将构建器用于执行搜索操作。

二、match查询

2.1.语法说明

全文检索的match和multi_match查询与match_all的APl基本一致,差别是查询条件,也就是query的部分。语法如下:

//单字段查询
QueryBuilders.matchQuery("all","如家");
//多字段查询
QueryBuilders.multiMatchQuery("如家","name","business");

2.2.单字段查询

利用QueryBuilders.matchQuery("all","如家")完成单个字段查询

/**
     * 单字段查询
     * @throws IOException
     */
    @Test
    void testMatchQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        SearchHits searchHits = response.getHits();
        //4.1.查询总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到:"+total+"条数据");
        //4.2.查询的结果数组
        for (SearchHit hit : searchHits.getHits()) {
            //4.3.获取文档source
            String json = hit.getSourceAsString();
            //4.4.打印输出
            System.out.println(json);
            //4.5.反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = "+hotelDoc);
        }
    }

执行后结果如下:

RestClient查询文档_Test_05

解析结果的代码是重复的代码,我们可以把它抽取出来,如下:

/**
     * 单字段查询
     * @throws IOException
     */
    @Test
    void testMatchQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        //3.发送请求
        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.查询的结果数组
        for (SearchHit hit : searchHits.getHits()) {
            //4.3.获取文档source
            String json = hit.getSourceAsString();
            //4.4.打印输出
            System.out.println(json);
            //4.5.反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = "+hotelDoc);
        }
    }

2.2.多字段查询

多字段查询利用,QueryBuilders.multiMatchQuery("如家","name","business");完成

/**
     * 多字段查询
     * @throws IOException
     */
    @Test
    void testMultiMatchQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.multiMatchQuery("如家", "name", "business"));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //调用方法解析结构
        handleResponse(response);
    }

三、精确查询

3.1.语法说明

精确查询常见的有term查询和range查询,同样利用QueryBuilders实现,语法如下:

//词条查询
QueryBuilders.termQuery("city","杭州");
//范围查询
QueryBuilders.rangeQuery("price").gte(100).lte(150);

3.2.精确查询:词条查询

案例如下:

@Test
    void testTermQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");

        //2.准备DSL
        request.source().query(QueryBuilders.termQuery("city","上海"));

        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析结构
        handleResponse(response);
    }

3.3.精确查询:范围查询

案例如下:查询价格在100到200之间的酒店信息

@Test
    void testRangeQuery() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");

        //2.准备DSL
        request.source().query(QueryBuilders.rangeQuery("price").gte(100).lte(200));

        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析结构
        handleResponse(response);
    }

执行后结果如下:

RestClient查询文档_字段_06

四、复合查询

4.1.语法说明

 复合查询,也就是组合查询,利用精确查询常见的有term查询和range查询,同样利用Query Builders实现:

//创建布尔查询
BoolQueryBuilder boolQuery=QueryBuilders.boolQuery();
//添加must条件
boolQuery.must(QueryBuilders.term Query("city","杭州"));
//添加filter条件
boolQuery.filter(QueryBuilders.range Query("price").lte(250));

4.2.案例

代码如下:

@Test
    void testBool() throws IOException {
        //1.准备request
        SearchRequest request = new SearchRequest("hotel");

        //2.准备DSL
        //2.1.准备BooleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.2.添加term
        boolQuery.must(QueryBuilders.termQuery("city", "上海"));
        //2.3.添加range 价格小于等于400的
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(400));

        request.source().query(boolQuery);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析结构
        handleResponse(response);
    }

执行后如下:

RestClient查询文档_Test_07

五、排序、分页、高亮

5.1.排序和分页

搜索结果的排序和分页是与query同级的参数,对应的API如下:

RestClient查询文档_字段_08

代码如下:

@Test
    void testPageAndSort() throws IOException {
        //页码和每页大小
        int page=1;
        int size=5;

        //1.准备request
        SearchRequest request = new SearchRequest("hotel");

        //2.准备DSL
        //2.1.准备Query
        request.source().query(QueryBuilders.matchAllQuery());
        //2.2.排序
        request.source().sort("price", SortOrder.ASC);
        //2.3.分页
        request.source().from((page-1)*size).size(size);

        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析结构
        handleResponse(response);
    }

执行后结果如下:

RestClient查询文档_System_09

5.2.高亮

高亮API包括请求DSL和结果解析两部分

5.2.1.高亮请求DSL构建

语法如下:

RestClient查询文档_System_10

代码如下:

@Test
    void testHighlight() throws IOException {

        //1.准备request
        SearchRequest request = new SearchRequest("hotel");

        //2.准备DSL
        //2.1.准备Query
        request.source().query(QueryBuilders.matchQuery("all", "如家"));
        //2.2.高亮: 由于上面查询的拷贝字段all,下面高亮显示的指定的是name字段,不一致,则需设置requireFieldMatch(false)
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析结构
        handleResponse(response);
    }

查看结果并没有高亮显示的部分,因为这里我们只是做了高亮的构建部分,结果解析部分还没有做,如下:

RestClient查询文档_System_11

5.2.2.高亮结果解析

语法如下:

RestClient查询文档_字段_12

代码如下:

@Test
    void testHighlight() throws IOException {

        //1.准备request
        SearchRequest request = new SearchRequest("hotel");

        //2.准备DSL
        //2.1.准备Query
        request.source().query(QueryBuilders.matchQuery("all", "如家"));
        //2.2.高亮: 由于上面查询的拷贝字段all,下面高亮显示的指定的是name字段,不一致,则需设置requireFieldMatch(false)
        request.source().highlighter(
                new HighlightBuilder()
                        .field("name")
                        .requireFieldMatch(false));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4.解析响应
        SearchHits searchHits = response.getHits();
        //4.1.获取总条数
        TotalHits total = searchHits.getTotalHits();
        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);
            //获取高亮结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();

            //Spring给我们提供了一个工具类,为我们判断是否为空:CollectionUtils.isEmpty()
            if(!CollectionUtils.isEmpty(highlightFields)){
                //根据字段名获取高亮结果
                HighlightField highlightField = highlightFields.get("name");
                if(highlightField != null){
                    //获取高亮的值
                    String name = highlightField.getFragments()[0].string();
                    //覆盖非高亮结果
                    hotelDoc.setName(name);
                }
            }
            System.out.println("hotelDoc = "+hotelDoc);
        }
    }

执行后结果如下:

RestClient查询文档_System_13