【SpringCloud——Elasticsearch(中)】

一、DSL查询语法以及整合JAVA代码使用

以下操作案例均基于上篇的hotel索引库及其数据进行。

 1、查询基本语法

GET /indexName/_search
{
  "query": {
    "查询类型":{
      "查询条件":"条件值"
    }
  }
}

2、查询所有

2.1、DSL语句

#查询所有
GET /hotel/_search
{
  "query": {
    "match_all": {
    }
  }
}

2.2、JAVA

    //match_all查询所有
    @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);
        showResult(response);
    }

注:showResult方法是将返回的响应进行解析,代码如下:

    private void showResult(SearchResponse response){
        //4.解析结果
        SearchHits searchHits = response.getHits();
        //4.1、查询结果总条数
        long value = searchHits.getTotalHits().value;
        System.out.println("共" + value + "条");
        //4.2、查询到的结果数据
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            HotelDoc doc = JSON.parseObject(json,HotelDoc.class);
            System.out.println(doc);
        }
    }

下文操作均使用此方法对响应进行解析。

 3、全文检索查询

全文检索查询会对用户输入的内容进行分词,常用于搜索框搜索。

3.1、DSL语句

#match查询
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "外滩"
    }
  }
}
#multi_match查询
#与match查询类似,只不过允许同时查询多个字段
GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "外滩如家",
      "fields": ["business","name","brand"]
    }
  }
}

3.2、JAVA

    //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);
        showResult(response);
    }
    //multi_match查询
    @Test
    void testMultiMatch() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        String[] fields = {"brand", "business", "name"};
        request.source().query(QueryBuilders.multiMatchQuery("外滩如家",fields));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        showResult(response);
    }

4、精确查询

精确查询一般是查找keyword、数值、日期、boolean等类型字段。

  • term:根据词条精确值查询
  • range:根据值的范围查询

 4.1、DSL语句

#精确查询(term精确值)
GET /hotel/_search
{
  "query": {
    "term": {
      "brand": {
        "value": "7天酒店"
      }
    }
  }
}
#精确查询(range范围)
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 300,
        "lte": 400
      }
    }
  }
}

4.2、JAVA

    //精确查询
    @Test
    void testTerm() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.termQuery("brand","7天酒店"));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        showResult(response);
    }
    //范围查询
    @Test
    void testRange() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.rangeQuery("price").gte(300).lte(400));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        showResult(response);
    }

5、地理查询

  • geo_bounding_box:查询geo_point值落在某个矩形范围内的所有文档。(不常用)
  • geo_distance:查询到指定中心点小于某个距离值的所有文档。(以下操作均针对此查询)

5.1、DSL语句

#地理查询
GET /hotel/_search
{
  "query": {
    "geo_distance":{
      "distance":"3km",
      "location":"31.21,121.5"
    }
  }
}

5.2、JAVA

使用第三方工具获取当前地理位置,发送至后端,后端根据传递的地理位置对酒店距离进行排序后返回。(附近的酒店功能)

            //2.3、距离排序
            if (params.getLocation() != null && !params.getLocation().equals("")){
                request.source().sort(SortBuilders.
                        geoDistanceSort("location",new GeoPoint(params.getLocation()))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS));
            }

6、复合查询

6.1、function score:算分函数查询,可以控制文档相关性算分,控制文档排名。

①、DSL语句

#相关性算分(function score查询)
GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "all": "外滩"
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "brand": "如家"
            }
          }
          , "weight": 10
        }
      ],
      "boost_mode": "multiply"
    }
  }
}

②、JAVA案例——对付了广告费的酒店进行排名靠前展示

            //2.算分控制
            FunctionScoreQueryBuilder functionScoreQuery =
                    QueryBuilders.functionScoreQuery(
                            //原始查询,相关性算分的查询
                            boolQuery,
                            //function score数组
                            new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                                    //其中的一个function score元素
                                    new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                                            //过滤条件
                                            QueryBuilders.termQuery("isAD",true),
                                            //算分函数
                                            ScoreFunctionBuilders.weightFactorFunction(10)
                                    )
                            });
            request.source().query(functionScoreQuery);

6.2、Boolean Query(复合查询)

①、DSL语句

搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店:

#复合查询(Boolean Query)
GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}

②、JAVA

    //复合查询
    @Test
    void testBoolean() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.matchQuery("name","如家"));
        boolQuery.mustNot(QueryBuilders.rangeQuery("price").gt(400));
        boolQuery.filter(QueryBuilders.geoDistanceQuery("location").distance("10km"));
        request.source().query(boolQuery);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        showResult(response);
    }

二、搜索结果处理以及整合JAVA代码使用

1、排序

elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

1.1、DSL语句

查询所有酒店并按照酒店评分降序排列,评分一致时按照酒店价格升序排列。

#排序
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score":  "desc"
    },
    {
      "price": "asc"
    }
  ]
}

 地理坐标排序:

#找到108.94647 , 34.34727 周围的酒店,并升序排序
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 34.34727,
          "lon": 108.94647
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

1.2、JAVA

    //排序
    @Test
    void testSort() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        request.source().sort("score", SortOrder.DESC);
        request.source().sort("price",SortOrder.ASC);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        showResult(response);
    }

 地理坐标排序:

            //2.3、距离排序
            if (params.getLocation() != null && !params.getLocation().equals("")){
                request.source().sort(SortBuilders.
                        geoDistanceSort("location",new GeoPoint(params.getLocation()))
                        .order(SortOrder.ASC)
                        .unit(DistanceUnit.KILOMETERS));
            }

2、分页

2.1、DSL语句

#分页查询
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "price":  "asc"
    }
  ],
  "from": 20,
  "size": 10
}

2.2、JAVA

    //分页
    @Test
    void testLimit() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchAllQuery());
        request.source().sort("price",SortOrder.ASC);
        request.source().from(20);
        request.source().size(10);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        showResult(response);
    }

3、高亮

高亮就是在搜索结果中把搜索关键字突出显示。

3.1、DSL语句

#高亮查询处理
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  }, 
  "highlight": {
    "fields": {
      "name": {
        "require_field_match": "false"
      }
    }
  }
}

3.2、JAVA

    //高亮
    @Test
    void testLight() throws IOException {
        //1.准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source().query(QueryBuilders.matchQuery("all","如家"));
        request.source().highlighter(new HighlightBuilder().field("name").requireFieldMatch(false));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.解析结果
        SearchHits searchHits = response.getHits();
        //4.1、查询结果总条数
        long value = searchHits.getTotalHits().value;
        System.out.println("共" + value + "条");
        //4.2、查询到的结果数据
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String json = hit.getSourceAsString();
            HotelDoc doc = JSON.parseObject(json,HotelDoc.class);
            //获取高亮结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (!CollectionUtils.isEmpty(highlightFields)){
                //根据字段名获取高亮结果
                HighlightField highlightField = highlightFields.get("name");
                if (highlightField != null){
                    //获取高亮值
                    String name = highlightField.getFragments()[0].toString();
                    //覆盖非高亮结果
                    doc.setName(name);
                }
            }
            System.out.println(doc);
        }
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值