• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

elasticsearch-数据聚合

武飞扬头像
Fairy要carry
帮助1

目录

介绍

 实际操作

DSL实现Metrics聚合(嵌套聚合)

RestClient实现聚合(以酒店品牌为例)

实现对酒店品牌、城市、星级的过滤


补6.20:

介绍

聚合:实现对文档数据的统计、分析以及运算,类似于分组group by

学新通

既然是完成数据的统计,说明我们的文档中聚合字段类型是不能分词type不能是text,不然你一种字段来了好几个,不能分组;

所以说参与聚合的字段类型:可以是keyword(不参与分词)、日期and布尔类型的等等;

学新通

聚合三要素:聚合名称、聚合类型、聚合字段

聚合可配置的属性:

学新通

 实际操作

学新通

  1.  
    GET /hotel/_search
  2.  
    {
  3.  
    "size": 0,
  4.  
    "aggs": {
  5.  
    "brandAgg": {
  6.  
    "terms": {
  7.  
    "field": "brand",
  8.  
    "size": 20
  9.  
    }
  10.  
    }
  11.  
    }
  12.  
    }

修改排序规则(_count):

默认是降序,可以加一个order排序规则学新通

  1.  
    GET /hotel/_search
  2.  
    {
  3.  
    "size":0,
  4.  
    "aggs":{
  5.  
    "brandAgg":{
  6.  
    "terms": {
  7.  
    "field": "brand",
  8.  
    "size": 10,
  9.  
    "order": {
  10.  
    "_count": "asc"
  11.  
    }
  12.  
    }
  13.  
    }
  14.  
    }
  15.  
    }
学新通

 限定聚合范围

在这里,query的作用范围与aggs聚合同级,作用是限制聚合的文档范围

学新通


DSL实现Metrics聚合(嵌套聚合)

学新通

记住这里是每个品牌内做统计(要作一个限定) 

做一个聚合的嵌套,弄一个brand聚合的子聚合,统计分组后对每组的一个统计

学新通

 学新通

我们还可以再加一个打分的排序,对scoreAgg中的avg进行一个降序排序 

 学新通

  1.  
    #嵌套聚合
  2.  
    GET /hotel/_search
  3.  
    {
  4.  
    "size": 0,
  5.  
    "aggs": {
  6.  
    "brandAgg": {
  7.  
    "terms": {
  8.  
    "field": "brand",
  9.  
    "size": 10,
  10.  
    "order": {
  11.  
    "scoreAgg.avg": "desc"
  12.  
    }
  13.  
    },
  14.  
    "aggs": {
  15.  
    "scoreAgg": {
  16.  
    "stats": {
  17.  
    "field": "score"
  18.  
    }
  19.  
    }
  20.  
    }
  21.  
    }
  22.  
    }
  23.  
    }
学新通

RestClient实现聚合(以酒店品牌为例)

学新通

学新通  

结果响应

学新通

因为aggs聚合里面有一些限制条件:1.terms类型以及聚合名字 2.字段名 3.size

  1.  
    /**
  2.  
    * 聚合测试
  3.  
    */
  4.  
    @Test
  5.  
    void testAggreation() throws IOException {
  6.  
    //1.准备request
  7.  
    SearchRequest request = new SearchRequest("hotel");
  8.  
    //2.准备DSL
  9.  
    request.source().size(0);
  10.  
    //2.1聚合
  11.  
    request.source().aggregation(AggregationBuilders
  12.  
    .terms("brandAgg")
  13.  
    .field("brand")
  14.  
    .size(10));
  15.  
    //3.发出请求
  16.  
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  17.  
     
  18.  
    /**
  19.  
    * 解析响应
  20.  
    */
  21.  
    Aggregations aggregations = response.getAggregations();
  22.  
    //4.1根据聚合名称得到具体那个类型聚合
  23.  
    Terms brandTerms = aggregations.get("brandAgg");
  24.  
    //4.2然后得到buckets中的数据
  25.  
    List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
  26.  
    //4.3进行遍历,得到每一条数据
  27.  
    for (Terms.Bucket bucket : buckets) {
  28.  
    //4.4获取key
  29.  
    String key = bucket.getKeyAsString();
  30.  
    System.out.println(key);
  31.  
    }
  32.  
    }
学新通

 学新通


实现对酒店品牌、城市、星级的过滤

因为我们的酒店过滤不能是静态的,应该是你数据中有什么类型的酒店(杭州、上海...),就展示能够选择什么类型的;

并且我们返回数据应该是map类型:

学新通

对接前端接口,将数据显示上去

学新通

 流程

1.得到request对象后,先设置size

2.然后进行多字段过滤(包括:酒店名称,地区,星级,以及广告打分)

3.聚合:对城市。品牌、星级进行分组

4.发送请求

5.对响应response进行解析,根据聚合名称得到里面的数据

  1.  
    /**
  2.  
    * 实现字段的聚合过滤
  3.  
    * @return
  4.  
    */
  5.  
    @Override
  6.  
    public Map<String, List<String>> filters(RequestParams params) throws IOException {
  7.  
     
  8.  
    SearchRequest request = new SearchRequest("hotel");
  9.  
    /**
  10.  
    * 准备DSL语句
  11.  
    */
  12.  
    /*1.设置size*/
  13.  
    request.source().size(0);
  14.  
     
  15.  
    extracted(params,request);
  16.  
     
  17.  
    /*2.聚合:城市,品牌,星级进行分组*/
  18.  
    request.source().aggregation(AggregationBuilders
  19.  
    .terms("brandAgg")
  20.  
    .field("brand")
  21.  
    .size(100));
  22.  
    request.source().aggregation(AggregationBuilders
  23.  
    .terms("cityAgg")
  24.  
    .field("city")
  25.  
    .size(100));
  26.  
    request.source().aggregation(AggregationBuilders
  27.  
    .terms("starAgg")
  28.  
    .field("starName")
  29.  
    .size(100));
  30.  
     
  31.  
    /*3.发出请求,得到响应*/
  32.  
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
  33.  
     
  34.  
    /**
  35.  
    * 4.对响应进行解析
  36.  
    */
  37.  
    HashMap<String, List<String>> map = new HashMap<>();
  38.  
    Aggregations aggregations = response.getAggregations();
  39.  
    /*4.1根据聚合名称得到品牌数据*/
  40.  
    ArrayList<String> brandList = getStrings(aggregations,"brandAgg");
  41.  
    /*4.2将聚合后的数据放入map中*/
  42.  
    map.put("Brand",brandList);
  43.  
     
  44.  
    ArrayList<String> cityList = getStrings(aggregations, "cityAgg");
  45.  
    map.put("City",cityList);
  46.  
     
  47.  
    ArrayList<String> starList = getStrings(aggregations, "starAgg");
  48.  
    map.put("StarName",brandList);
  49.  
    return map;
  50.  
    }
  51.  
     
  52.  
    /**
  53.  
    * 辅助方法:根据聚合名称得到属于该聚合的所有数据
  54.  
    * @param aggregations
  55.  
    * @return
  56.  
    */
  57.  
    private ArrayList<String> getStrings(Aggregations aggregations,String name) {
  58.  
    /*得到其中一种聚合*/
  59.  
    Terms brandTerms = aggregations.get(name);
  60.  
    List<? extends Terms.Bucket> buckets = brandTerms.getBuckets();
  61.  
    /*专门存放key*/
  62.  
    ArrayList<String> list = new ArrayList<>();
  63.  
    for (Terms.Bucket bucket : buckets) {
  64.  
    String key = bucket.getKeyAsString();
  65.  
    list.add(key);
  66.  
    }
  67.  
    return list;
  68.  
    }
学新通

 多字段过滤(包括:城市、品牌、酒店星级以及广告算分控制)

  1.  
    /**
  2.  
    * 辅助
  3.  
    *
  4.  
    * @param params
  5.  
    */
  6.  
    private void extracted(RequestParams params, SearchRequest request) {
  7.  
    /**
  8.  
    * 辅助字段查询:城市、品牌、酒店星级
  9.  
    */
  10.  
    BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  11.  
    /*关键字搜索*/
  12.  
    if ((params.getKey()) == null || "".equals(params.getKey())) {
  13.  
    boolQuery.must(QueryBuilders.matchAllQuery());
  14.  
    } else {
  15.  
    boolQuery.must(QueryBuilders.matchQuery("name", params.getKey()));
  16.  
    }
  17.  
     
  18.  
    /*城市条件*/
  19.  
    if (params.getCity() != null && !params.getCity().equals("")) {
  20.  
    boolQuery.filter(QueryBuilders.termQuery("city", params.getCity()));
  21.  
    }
  22.  
     
  23.  
    /*品牌条件*/
  24.  
    if (params.getBrand() != null && !params.getBrand().equals("")) {
  25.  
    boolQuery.filter(QueryBuilders.termQuery("brand", params.getBrand()));
  26.  
    }
  27.  
     
  28.  
    /*星级条件*/
  29.  
    if (params.getStarName() != null && !params.getStarName().equals("")) {
  30.  
    boolQuery.filter(QueryBuilders.termQuery("startName", params.getStarName()));
  31.  
    }
  32.  
     
  33.  
    /*价格*/
  34.  
    if (params.getMiniPrice() != null && params.getMaxPrice() != null) {
  35.  
    boolQuery.filter(QueryBuilders
  36.  
    .rangeQuery("price")
  37.  
    .gte(params.getMiniPrice()).lte(params.getMaxPrice()));
  38.  
    }
  39.  
     
  40.  
    /**
  41.  
    * 算分控制
  42.  
    */
  43.  
    FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(
  44.  
    //1.基本查询:前面条件查询的内容进行重新打分
  45.  
    boolQuery,
  46.  
    //2.打分数组
  47.  
    new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
  48.  
    //3.其中一个打分
  49.  
    new FunctionScoreQueryBuilder.FilterFunctionBuilder(
  50.  
    //过滤条件
  51.  
    QueryBuilders.termQuery("isAD", true),
  52.  
    // 算分函数
  53.  
    ScoreFunctionBuilders.weightFactorFunction(5)
  54.  
    )
  55.  
    }
  56.  
    );
  57.  
     
  58.  
    request.source().query(functionScoreQueryBuilder);
  59.  
    }
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgggabe
系列文章
更多 icon
同类精品
更多 icon
继续加载