elasticsearch高级功能之聚合查询

elasticsearch高级功能之聚合查询,是比较复杂的的高级功能,其中包含相关的统计功能,比如最大值、最小值、平均值、求和等,又比如筛选完数据后,还需要过滤筛选项,今天我们详细分析一下:

一、聚合指标

1、基本的统计指标

1.1、计算基本类型的平均值

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
      "avg": {
        "field": "price"
      }
    }
  }
}

1.2、计算非基本类型的平均值

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
      "avg": {
        "field": "comment.properties.good"
      }
    }
  }
}

java客户端:

 public void getAvgAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest(" scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String aggName = "my_agg";//聚合的名称
        //定义avg聚合,指定字段为价格
        AvgAggregationBuilder aggregationBuilder = AggregationBuilders.avg(aggName).field("price");
        searchSourceBuilder.aggregation(aggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Avg avg = aggregations.get(aggName);//获取avg聚合返回的对象
        String key = avg.getName();//获取聚合名称
        double avgValue = avg.getValue();//获取聚合值
        System.out.println("key=" + key + ",avgValue=" + avgValue);//打印结果
    }

1.3、返回多个统计数据

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
      "stats": {
        "field": "price"
      }
    }
  }
}

java客户端

public void getStatsAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String aggName = "my_agg";//聚合的名称
        //定义stats聚合,指定字段为价格
        StatsAggregationBuilder aggregationBuilder = AggregationBuilders.stats(aggName).field("price");
        searchSourceBuilder.aggregation(aggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Stats stats = aggregations.get(aggName);//获取stats聚合返回的对象
        String key = stats.getName();//获取聚合名称
        double sumVal = stats.getSum();//获取聚合加和值
        double avgVal = stats.getAvg();//获取聚合平均值
        long countVal = stats.getCount();//获取聚合文档数量值
        double maxVal = stats.getMax();//获取聚合最大值
        double minVal = stats.getMin();//获取聚合最小值
        System.out.println("key=" + key);//打印聚合名称
        System.out.println("sumVal=" + sumVal + ",avgVal=" + avgVal + ",countVal=" + countVal + ",maxVal=" + maxVal + ",minVal=" + minVal);//打印结果
    }

 2、空值处理

2.1、基本类型非空值的个数

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
       "value_count": {
         "field": "price"
       }
    }
  }
}

java客户端

 public void getValueCountAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String aggName = "my_agg";//聚合的名称
        //定义value_count聚合,指定字段为价格
        ValueCountAggregationBuilder aggregationBuilder = AggregationBuilders.count(aggName).field("price");
        aggregationBuilder.missing("200");
        searchSourceBuilder.aggregation(aggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        ValueCount valueCount = aggregations.get(aggName);//获取value_count聚合返回的对象
        String key = valueCount.getName();//获取聚合名称
        long count = valueCount.getValue();//获取聚合值
        System.out.println("key=" + key + ",count=" + count);//打印结果
    }

 2.2、数组非空值个数

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
       "value_count": {
         "field": "tag"
       }
    }
  }
}

2.3、空值替换相加

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
       "sum": {
         "field": "price",
         "missing": 200
       }
    }
  }
}

java客户端

public void getSumAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String aggName = "my_agg";//聚合的名称
        //定义sum聚合,指定字段为价格
        SumAggregationBuilder aggregationBuilder = AggregationBuilders.sum(aggName).field("price");
        aggregationBuilder.missing("200");
        searchSourceBuilder.aggregation(aggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Sum sum = aggregations.get(aggName);//获取sum聚合返回的对象
        String key = sum.getName();//获取聚合名称
        double sumVal = sum.getValue();//获取聚合值
        System.out.println("key=" + key + ",count=" + sumVal);//打印结果
    }

 二、桶聚合查询

1、单维度桶聚合查询

1.1、按照城市聚合查询

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
       "terms": {
         "field": "city"
       }
    }
  }
}

java客户端

public void getBucketDocCountAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String termsAggName = "my_terms";//指定聚合的名称
        //定义terms聚合,指定字段为城市
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termsAggName).field("full_room");

        searchSourceBuilder.aggregation(termsAggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(termsAggName);//获取聚合返回的对象

        for (Terms.Bucket bucket : terms.getBuckets()) {
            String bucketKey = bucket.getKeyAsString();//获取桶名称
            long docCount = bucket.getDocCount();//获取文档个数
            System.out.println("termsKey=" + bucketKey + ",docCount=" + docCount);
        }
    }

 1.2、范围聚合查询

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
       "range": {
         "field": "price",
         "ranges": [
           {
             "to": 20
           },
           {
             "from": 100, 
             "to": 50
           },
           {
             "from": 1000, 
             "to": 500
           }
         ]
       }
    }
  }
}

java客户端

public void getRangeDocCountAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String rangeAggName = "my_range";//sum聚合的名称
        //定义range聚合,指定字段为price
        RangeAggregationBuilder rangeAgg = AggregationBuilders.range(rangeAggName).field("price");
        rangeAgg.addRange(new RangeAggregator.Range(null,null,200d));
        rangeAgg.addRange(new RangeAggregator.Range(null,200d,500d));
        rangeAgg.addRange(new RangeAggregator.Range(null,500d,null));
        searchSourceBuilder.aggregation(rangeAgg);//添加range聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Range range = aggregations.get(rangeAggName);//获取range聚合返回的对象
        for (Range.Bucket bucket : range.getBuckets()) {
            String bucketKey = bucket.getKeyAsString();//获取桶名称
            long docCount = bucket.getDocCount();//获取聚合文档个数
            System.out.println("bucketKey=" + bucketKey + ",docCount=" + docCount);
        }
    }

 1.3、按照城市维度聚合查询各城市的平均价格

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
       "terms": {
         "field": "city"
       },
       "aggs": {
         "my_sum": {
           "sum": {
             "field": "price",
             "missing": 100
           }
         }
       }
    }
  }
}

java客户端

public void getBucketAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String termsAggName = "my_terms";//sum聚合的名称
        //定义terms聚合,指定字段为城市
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termsAggName).field("city");
        String sumAggName = "my_sum";//sum聚合的名称
        //定义sum聚合,指定字段为价格
        SumAggregationBuilder sumAggregationBuilder = AggregationBuilders.sum(sumAggName).field("price");
        //定义聚合的父子关系
        termsAggregationBuilder.subAggregation(sumAggregationBuilder);
        searchSourceBuilder.aggregation(termsAggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(termsAggName);//获取sum聚合返回的对象

        for (Terms.Bucket bucket : terms.getBuckets()) {
            String termsKey = bucket.getKey().toString();
            System.out.println("termsKey=" + termsKey);
            Sum sum = bucket.getAggregations().get(sumAggName);
            String key = sum.getName();//获取聚合名称
            double sumVal = sum.getValue();//获取聚合值
            System.out.println("key=" + key + ",count=" + sumVal);//打印结果
        }
    }

 2、多维度桶嵌套聚合查询

查询景区时搜索各城市的满房状态和平均价格等

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "group_city": {
       "terms": {
         "field": "city"
       },
       "aggs": {
         "grup_full_room": {
           "terms": {
             "field": "full"
           },
           "aggs": {
             "my_sum": {
               "avg": {
                 "field": "price",
                 "missing": 100
               }
               
             }
           }
         }
       }
    }
  }
}

java客户端

public void getExternalBucketAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        String aggNameCity = "my_terms_city";//按城市聚合的名称
        //定义terms聚合,指定字段为城市
        TermsAggregationBuilder termsAggCity = AggregationBuilders.terms(aggNameCity).field("city");

        String aggNameFullRoom = "my_terms_full_room";//按满房状态聚合的名称
        //定义terms聚合,指定字段为满房状态
        TermsAggregationBuilder termsArrFullRoom = AggregationBuilders.terms(aggNameCity).field("full_room");

        String sumAggName = "my_sum";//sum聚合的名称
        //定义sum聚合,指定字段为价格
        SumAggregationBuilder sumAgg = AggregationBuilders.sum(sumAggName).field("price");

        //定义聚合的父子关系
        termsArrFullRoom.subAggregation(sumAgg);
        termsAggCity.subAggregation(termsArrFullRoom);
        searchSourceBuilder.aggregation(termsAggCity);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(aggNameCity);//获取sum聚合返回的对象
        for (Terms.Bucket bucket : terms.getBuckets()) {//遍历第一层bucket
            String termsKeyCity = bucket.getKey().toString();//获取第一层bucket名称
            System.out.println("--------" + "termsKeyCity=" + termsKeyCity + "--------");
            Terms termsFullRom = bucket.getAggregations().get(aggNameCity);
            for (Terms.Bucket bucketFullRoom : termsFullRom.getBuckets()) {//遍历第二层bucket
                String termsKeyFullRoom = bucketFullRoom.getKeyAsString();//获取第二层bucket名称
                System.out.println("termsKeyFullRoom=" + termsKeyFullRoom);
                Sum sum = bucketFullRoom.getAggregations().get(sumAggName);//获取聚合指标
                String key = sum.getName();//获取聚合指标名称
                double sumVal = sum.getValue();//获取聚合指标值
                System.out.println("key=" + key + ",count=" + sumVal);//打印结果
            }
        }
    }

 3、地理位置聚合

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "my_agg": {
      "geo_distance": {
        "field": "location",
        "origin": {
          "lat": 39.915143,
          "lon": 116.4039
        } 
        , "unit": "km",
         "ranges": [
           {
             "to": 2
           },
           {
             "from": 3, 
             "to": 10
           },
           {
             "from": 10
           }
         ]
      },
      "aggs": {
        "my_min": {
          "min": {
            "field": "price",
            "missing": 200
          }
        }
      }
    }
  }
}

java客户端

public void geGeoDistanceAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String geoDistanceAggName = "location";//sum聚合的名称
        //定义GeoDistance聚合
        GeoDistanceAggregationBuilder geoDistanceAgg=AggregationBuilders.geoDistance(geoDistanceAggName,new GeoPoint(39.915143,116.4039));
        geoDistanceAgg.unit(DistanceUnit.KILOMETERS);
        geoDistanceAgg.field("location");
        //指定分桶范围规则
        geoDistanceAgg.addRange(new GeoDistanceAggregationBuilder.Range(null,0d,3d));
        geoDistanceAgg.addRange(new GeoDistanceAggregationBuilder.Range(null,3d,110d));
        geoDistanceAgg.addRange(new GeoDistanceAggregationBuilder.Range(null,110d,null));
        String minAggName = "my_min";//min聚合的名称
        //定义sum聚合,指定字段为价格
        MinAggregationBuilder minAgg = AggregationBuilders.min(minAggName).field("price");
        minAgg.missing(100);//指定默认值
        //定义聚合的父子关系
        geoDistanceAgg.subAggregation(minAgg);
        searchSourceBuilder.aggregation(geoDistanceAgg);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        //执行查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        ParsedGeoDistance range = aggregations.get(geoDistanceAggName);//获取GeoDistance聚合返回的对象
        for (Range.Bucket  bucket : range.getBuckets()) {
            String termsKey = bucket.getKeyAsString();//获取bucket名称的字符串形式
            System.out.println("termsKey=" + termsKey);
            ParsedMin min = bucket.getAggregations().get(minAggName);
            String key = min.getName();//获取聚合名称
            double minVal = min.getValue();//获取聚合值
            System.out.println("key=" + key + ",min=" + minVal);//打印结果
        }
    }

三、聚合方式

1、先查询在聚合

GET /nandao_scenic/_search
{
  "size": 0,
  "query": {
    "term": {
      "city": {
        "value": "河南"
      }
    }
  }, 
  "aggs": {
    "my_agg": {
      "avg": {
        "field": "price"
      }
    }
  }
}

java客户端

public void getQueryAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        String avgAggName = "my_avg";//avg聚合的名称
        //定义sum聚合,指定字段为价格
        AvgAggregationBuilder avgAgg = AggregationBuilders.avg(avgAggName).field("price");

        searchSourceBuilder.aggregation(avgAgg);//添加聚合
        searchSourceBuilder.query(QueryBuilders.termQuery("city", "北京"));//构建query查询
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        SearchHits searchHits = searchResponse.getHits();//获取搜索结果集
        System.out.println("---------------hit--------------");
        for (SearchHit searchHit : searchHits) {//遍历搜索结果集
            String index = searchHit.getIndex();//获取索引名称
            String id = searchHit.getId();//获取文档_id
            Float score = searchHit.getScore();//获取得分
            String source = searchHit.getSourceAsString();//获取文档内容
            System.out.println("index=" + index + ",id=" + id + ",source=" + source);//打印数据
        }
        System.out.println("---------------agg--------------");
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        ParsedAvg avg = aggregations.get(avgAggName);//获取sum聚合返回的对象
        String avgName = avg.getName();//获取聚合名称
        double avgVal = avg.getValue();//获取聚合值
        System.out.println("avgName=" + avgName + ",avgVal=" + avgVal);//打印结果
    }

 2、前过滤器

GET /nandao_scenic/_search
{
  "size": 0,
  "query": {
    "term": {
      "city": {
        "value": "河南"
      }
    }
  }, 
  "aggs": {
    "my_agg": {
      "filter": {
        "term": {
          "full": false
        }
      }, 
      "aggs": {
        "my_avg": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}

java客户端

public void getFilterAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String filterAggName = "my_terms";//sum聚合的名称
        TermQueryBuilder termQueryBuilder=QueryBuilders.termQuery("full",true);
        FilterAggregationBuilder filterAggregationBuilder=AggregationBuilders.filter(filterAggName,termQueryBuilder);

        String avgAggName = "my_avg";//avg聚合的名称
        //定义sum聚合,指定字段为价格
        AvgAggregationBuilder avgAgg= AggregationBuilders.avg(avgAggName).field("price");

        filterAggregationBuilder.subAggregation(avgAgg);//为filter聚合添加子聚合
        searchSourceBuilder.aggregation(filterAggregationBuilder);//添加聚合
        searchSourceBuilder.query(QueryBuilders.termQuery("city", "北京"));//构建term查询
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        ParsedFilter filter = aggregations.get(filterAggName);//获取sum聚合返回的对象
        Avg avg =filter.getAggregations().get(avgAggName);
        String key = avg.getName();//获取聚合名称
        double avgVal = avg.getValue();//获取聚合值
        System.out.println("key=" + key + ",avgVal=" + avgVal);//打印结果
    }

 3、后过滤器

GET /nandao_scenic/_search
{
  "size": 0,
  "query": {
    "match": {
      "title": "山"
    }
  }, 
  "post_filter": {
    "term": {
      "city": "北京"
    }
  },
  "aggs": {
      "my_avg": {
        "avg": {
          "field": "price",
          "missing": 100
        }
      }
    }
}

java客户端

public void getPostFilterAggSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        String avgAggName = "my_avg";//avg聚合的名称
        //定义sum聚合,指定字段为价格
        AvgAggregationBuilder avgAgg= AggregationBuilders.avg(avgAggName).field("price");
        avgAgg.missing(200);//设置默认值为200
        searchSourceBuilder.aggregation(avgAgg);//添加聚合
        searchSourceBuilder.query(QueryBuilders.matchQuery("title", "假日"));//构建term查询
        TermQueryBuilder termQueryBuilder=QueryBuilders.termQuery("city","北京");
        searchSourceBuilder.postFilter(termQueryBuilder);
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Avg avg =aggregations.get(avgAggName);
        String key = avg.getName();//获取聚合名称
        double avgVal = avg.getValue();//获取聚合值
        System.out.println("key=" + key + ",avgVal=" + avgVal);//打印结果
    }

四、聚合排序

1、 按文档计数排序

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "group_city": {
      "terms": {
        "field": "city",
        "order": {
          "_count": "asc"
        }
      },
      "aggs": {
      "my_avg": {
        "avg": {
          "field": "price",
          "missing": 100
        }
      }
    }
    }
  }
}

java客户端

public void getAggDocCountOrderSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String termsAggName = "my_terms";//sum聚合的名称
        //定义terms聚合,指定字段为城市
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termsAggName).field("city");
        BucketOrder bucketOrder=BucketOrder.count(true);
        termsAggregationBuilder.order(bucketOrder);
        String avgAggName = "my_avg";//avg聚合的名称
        //定义sum聚合,指定字段为价格
        SumAggregationBuilder avgAgg = AggregationBuilders.sum(avgAggName).field("price");
        //定义聚合的父子关系
        termsAggregationBuilder.subAggregation(avgAgg);
        searchSourceBuilder.aggregation(termsAggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        SearchHits searchHits = searchResponse.getHits();//获取搜索结果集
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(termsAggName);//获取sum聚合返回的对象
        for (Terms.Bucket bucket : terms.getBuckets()) {
            String bucketKey = bucket.getKey().toString();
            System.out.println("termsKey=" + bucketKey);
            Sum sum = bucket.getAggregations().get(avgAggName);
            String key = sum.getName();//获取聚合名称
            double sumVal = sum.getValue();//获取聚合值
            System.out.println("key=" + key + ",count=" + sumVal);//打印结果
        }
    }

2、 按照聚合指标排序

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "group_city": {
      
      "terms": {
        "field": "city",
        "order": {
          "my_avg": "asc"
        }
      },
      "aggs": {
      "my_avg": {
        "avg": {
          "field": "price",
          "missing": 200
        }
      }
    }
    
    }
  }
}

java客户端

public void getAggMetricsOrderSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String termsAggName = "my_terms";//sum聚合的名称
        //定义terms聚合,指定字段为城市
        String avgAggName = "my_avg";//avg聚合的名称
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termsAggName).field("city");
        BucketOrder bucketOrder=BucketOrder.aggregation(avgAggName,true);
        termsAggregationBuilder.order(bucketOrder);

        //定义sum聚合,指定字段为价格
        AvgAggregationBuilder avgAgg = AggregationBuilders.avg(avgAggName).field("price");
        //定义聚合的父子关系
        termsAggregationBuilder.subAggregation(avgAgg);
        searchSourceBuilder.aggregation(termsAggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(termsAggName);//获取聚合返回的对象
        for (Terms.Bucket bucket : terms.getBuckets()) {
            String bucketKey = bucket.getKey().toString();
            System.out.println("termsKey=" + bucketKey);
            Avg avg = bucket.getAggregations().get(avgAggName);
            String key = avg.getName();//获取聚合名称
            double avgVal = avg.getValue();//获取聚合值
            System.out.println("key=" + key + ",avgVal=" + avgVal);//打印结果
        }
    }

 3、 分组key排序

GET /nandao_scenic/_search
{
  "size": 0,
  "aggs": {
    "group_city": {
      "terms": {
        "field": "city",
        "order": {
          "_key": "asc"
        }
      },
      "aggs": {
      "my_avg": {
        "avg": {
          "field": "price",
          "missing": 200
        }
      }
    }
    }
  }
}

java客户端

public void getAggKeyOrderSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String termsAggName = "my_terms";//sum聚合的名称
        //定义terms聚合,指定字段为城市
        String avgAggName = "my_avg";//avg聚合的名称
        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termsAggName).field("city");
        BucketOrder bucketOrder=BucketOrder.key(true);
        termsAggregationBuilder.order(bucketOrder);

        //定义sum聚合,指定字段为价格
        SumAggregationBuilder avgAgg = AggregationBuilders.sum(avgAggName).field("price");
        //定义聚合的父子关系
        termsAggregationBuilder.subAggregation(avgAgg);
        searchSourceBuilder.aggregation(termsAggregationBuilder);//添加聚合
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        SearchHits searchHits = searchResponse.getHits();//获取搜索结果集
        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(termsAggName);//获取sum聚合返回的对象
        for (Terms.Bucket bucket : terms.getBuckets()) {
            String bucketKey = bucket.getKey().toString();
            System.out.println("termsKey=" + bucketKey);
            Sum sum = bucket.getAggregations().get(avgAggName);
            String key = sum.getName();//获取聚合名称
            double sumVal = sum.getValue();//获取聚合值
            System.out.println("key=" + key + ",count=" + sumVal);//打印结果
        }
    }

五、聚合分页

1、Top hits 聚合分页

GET /nandao_scenic/_search
{
  "size": 0,
  "query": {
    "match": {
      "title": "山"
    }
  }, 
  "aggs": {
    "group_city": {
      "terms": {
        "field": "city"
      },
      "aggs": {
      "my_avg": {
        "top_hits": {
           "size": 10
        }
      }
    }
    }
  }
}

java客户端

public void getAggTopHitsSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("nandao_scenic");//创建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        String termsAggName = "my_terms";//sum聚合的名称

        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms(termsAggName).field("city");
        BucketOrder bucketOrder=BucketOrder.key(true);
        termsAggregationBuilder.order(bucketOrder);

        String topHitsAggName = "my_top";//avg聚合的名称
        TopHitsAggregationBuilder topHitsAgg=AggregationBuilders.topHits(topHitsAggName);
        topHitsAgg.size(3);
        //定义聚合的父子关系
        termsAggregationBuilder.subAggregation(topHitsAgg);
        searchSourceBuilder.aggregation(termsAggregationBuilder);//添加聚合
        searchSourceBuilder.query(QueryBuilders.matchQuery("title","金都"));
        searchRequest.source(searchSourceBuilder);//设置查询请求
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索

        Aggregations aggregations = searchResponse.getAggregations();//获取聚合结果
        Terms terms = aggregations.get(termsAggName);//获取sum聚合返回的对象
        for (Terms.Bucket bucket : terms.getBuckets()) {
            String bucketKey = bucket.getKey().toString();
            System.out.println("termsKey=" + bucketKey);
            TopHits topHits = bucket.getAggregations().get(topHitsAggName);
            SearchHit[] searchHits=topHits.getHits().getHits();
            for(SearchHit searchHit:searchHits){
                System.out.println(searchHit.getSourceAsString());
            }
        }
    }

此种分页影响性能,优化方向可以一次性存到redis,然后再redis里面做分页缓存

stringRedisTemplate.opsForList().range(key,0, 10); 

  2、Collapse 聚合分页

GET /nandao_scenic/_search
{
  "from": 0, 
  "size": 5,
  "query": {
    "match": {
      "title": "山"
    }
  },
  "collapse": {
    "field": "city"
  }
}

 java客户端

public void getCollapseAggSearch() throws IOException{
        //按照spu进行分组
        CollapseBuilder collapseBuilder = new CollapseBuilder("city");//按照城市进行分组
        SearchRequest searchRequest = new SearchRequest();//新建搜索请求
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("title", "金都"));//新建match查询
        searchSourceBuilder.collapse(collapseBuilder);//设置折叠
        searchRequest.source(searchSourceBuilder);//设置查询
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//执行搜索
        SearchHits searchHits = searchResponse.getHits();//获取搜索结果集
        for (SearchHit searchHit : searchHits) {//遍历搜索结果集
            String index = searchHit.getIndex();//获取索引名称
            String id = searchHit.getId();//获取文档_id
            Float score = searchHit.getScore();//获取得分
            String source = searchHit.getSourceAsString();//获取文档内容
            System.out.println("index=" + index + ",id=" + id + ",score=" + score + ",source=" + source);//打印数据
        }
    }

到此,聚合相关的查询分享完毕,大家一定要结合项目多多实战练习,定会早日掌握,下篇我们分析文本搜索相关的内容,敬请期待。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅灯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值