一.DSL查询分类

  • 查询所有:查询出所有数据,一般测试用。例如:match_all
  • 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配。例如:
    • match_query
    • multi_match_query
  • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。例如:
    • ids
    • range
    • term
  • 地理(geo)查询:根据经纬度查询。例如:
    • geo_distance
    • geo_bounding_box
  • 复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。例如:

    • bool
    • function_score

      二:基本语法

      match:根据一个字段查询
      term:根据词条精确值查询
      range:根据值的范围查询
      geo_distance(附近查询): 查询到指定中心点小于某个距离值的所有文档。
      fuction score:算分函数查询,可以控制文档相关性算分,控制文档排名
      image.png
      bool query:布尔查询,利用逻辑关系组合多个其它的查询,实现复杂搜索
      image.png

      2.搜索结果处理

      1.排序

      elasticsearch默认是根据相关度算分排序的,可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

      2.分页

      from:从第几个文档开始 第几页
      size:总共查询几个文档 每页显示多少条
      image.png

      3.高亮

      步骤:
      1.给文档中的所有关键字都添加一个标签,例如标签
      2.页面给标签编写CSS样式
      image.png

      三.代码实现

      准备客户端对象

      1. private RestHighLevelClient client;
      2. @BeforeEach
      3. public void init() {
      4. // 1.准备好Es的客户端对象
      5. client = new RestHighLevelClient(RestClient.builder(
      6. HttpHost.create("http://192.168.200.130:9200")
      7. ));
      8. }
      9. @AfterEach
      10. public void tearDown() {
      11. try {
      12. client.close();
      13. } catch (IOException e) {
      14. e.printStackTrace();
      15. }
      16. }

      1.查询

      步骤:
      1.创建请求
      2.执行请求
      3.解析响应结果

   //查询全部
    @Test
    public void matchAll() throws IOException {
        //1.创建请求
        SearchRequest request = new SearchRequest("hotel");
        SearchSourceBuilder source = request.source();
        //1.1构建条件
        source.query(QueryBuilders.matchAllQuery());
        //2.执行请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //3.解析结果
        printResult(response);
    }
private void printResult(SearchResponse response) {
        //3.解析结果
        SearchHits hits = response.getHits();
        System.out.println("查询到的文档数量:" + hits.getTotalHits().value);
        //遍历
        for (SearchHit searchHit : hits) {
            String hotelJson = searchHit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(hotelJson, HotelDoc.class);
        }

2.match查询

@Test
void testMatch() 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.解析响应
    handleResponse(response);

}

3.精确查询

精确查询主要是两者:

  • term:词条精确匹配
    source.query(QueryBuilders.termQuery("city", "上海"));
    
  • range:范围查询

    source.query(QueryBuilders.rangeQuery("price").gte(1000).lte(1500));
    

    4.布尔查询

    布尔查询是用must、must_not、filter等方式组合其它查询

     /*
       *   布尔查询
       *           包含: 上海外滩
       *                价格 1000-1500
       *                排除品牌
       * */
      @Test
      public void bool() throws IOException {
          //创建请求
          SearchRequest request = new SearchRequest("hotel");
          SearchSourceBuilder source = request.source();
          //构建请求条件
          //创建布尔条件
          BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
          //组合其他基础条件
          MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name", "上海外滩");
          boolQuery.must(matchQueryBuilder);
    
          RangeQueryBuilder priceBuilder = QueryBuilders.rangeQuery("price").gte(1000).lte(1500);
          boolQuery.filter(priceBuilder);
    
          TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("brand", "希尔顿");
          boolQuery.mustNot(termQueryBuilder);
    
          source.query(boolQuery);
          //执行请求
          SearchResponse search = client.search(request, RequestOptions.DEFAULT);
          //解析结果
          printResult(search);
      }
    

    5.排序、分页

    ```java public void sortAndPage() throws IOException {

      //定义第几页
      int page = 1;
      //定义每页显示多少条
      int size = 3;
    
      //创建请求
      SearchRequest request = new SearchRequest("hotel");
      SearchSourceBuilder source = request.source();
      //排序--->按照评价升序
      source.sort("score", SortOrder.ASC);
      //评分一直,按照价格降序
      source.sort("price", SortOrder.DESC);
    
      //分页
      source.from((page - 1) * size);
      source.size(size);
    
      //执行请求
      SearchResponse response = client.search(request, RequestOptions.DEFAULT);
      //解析结果
      printResult(response);
    

    }

<a name="wRHEr"></a>
## 6.高亮
高亮的代码与之前代码差异较大,有两点:

- 查询的DSL:其中除了查询条件,还需要添加高亮条件,同样是与query同级。
- 结果解析:结果除了要解析_source文档数据,还要解析高亮结果

**高亮查询必须使用全文检索查询,并且要有搜索关键字,将来才可以对关键字高亮。**
```java
 @Test
    public void highlight() throws IOException {
        //创建请求
        SearchRequest request = new SearchRequest("hotel");
        SearchSourceBuilder source = request.source();
        //1.1构建条件
        source.query(QueryBuilders.matchQuery("name", "外滩如家"));

        //高亮条件设置
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("name"); //那个字段高亮
        highlightBuilder.preTags("<span>"); //前置标签
        highlightBuilder.postTags("</span>"); //后置标签

        source.highlighter(highlightBuilder);
        //执行请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析结果
        printResult(response);
    }

解析结果

  //解析结果
    private void printResult(SearchResponse response) {
        //3.解析结果
        SearchHits hits = response.getHits();
        System.out.println("查询到的文档数量:" + hits.getTotalHits().value);
        //遍历
        for (SearchHit searchHit : hits) {
            String hotelJson = searchHit.getSourceAsString();
            HotelDoc hotelDoc = JSON.parseObject(hotelJson, HotelDoc.class);

            //单独获取高亮处理结果
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            //判断
            if (!CollectionUtils.isEmpty(highlightFields)) {
                // 文档name字段的高亮处理结果
                HighlightField highlightField = highlightFields.get("name");
                //拼接高亮字段
                String highlightResultStr = StringUtils.join(highlightField.getFragments());
                //用高亮处理结果替换之前的name字段内容
                hotelDoc.setName(highlightResultStr);
            }
            //输出文档
            System.out.println(hotelDoc);
        }
    }