• 数据聚合、


    数据聚合

    聚合(Aggregations):可以实现对文档数据的统计、分析、运算。

    常见的聚合有三类:

    • 桶(Bucket)聚合:用来对文档做分组

    ​ TermAggtegation:按照文档字段值分组

    ​ Date Histogram:按照日期阶梯分组

    • 度量(Metric)聚合:

    ​ Avg:求平均值

    ​ Max:求最大值

    ​ Min:求最小值

    ​ Status:同时求max、min、avg、sum等

    • 管道(pipeline)聚合:其他聚合的结果为基础做聚合

      具体可查阅官方文档[Aggregations | Elasticsearch Guide 8.3] | Elastic

    DSL实现Bucket聚合

    按照品牌名聚合

    #聚合功能
    GET /hotel/_search
    {
      "size":0,         #设置size为0,结果中不包含文档,只包含聚合结果
      "aggs": {
        "brandAgg": {    #给聚合起的名字
          "terms": {
            "field": "brand",
            "size": 10      #希望获取的聚合结果的数量
          }
        }
      }
    }
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    默认情况下,Bucker聚合会统计Bucket内文档的数量,记为_count,并按照__count降序排序

    #聚合功能
    GET /hotel/_search
    {
      "size":0,
      "aggs": {
        "brandAgg": {
          "terms": {
            "field": "brand",
            "size": 10,
            "order": {
              "_count": "asc"
            }
          }
        }
      }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    限定聚合范围

    只要添加query条件即可

    #聚合功能
    GET /hotel/_search
    {
      "query": {
        "range": {
          "price": {
            "lte": 200
          }
        }
      }, 
      "size":0,
      "aggs": {
        "brandAgg": {
          "terms": {
            "field": "brand",
            "size": 10,
            "order": {
              "_count": "asc"
            }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    聚合必须的三要素:

    • 聚合名称
    • 聚合类型
    • 聚合字段

    聚合可配置的属性有:

    • size:指定聚合结果数量
    • order:指定聚合结果排序方式
    • field:指定聚合字

    DSL实现Metrics聚合

    取每个品牌的用户评分的min,max,avg

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

    在这里插入图片描述

    对平均分进行排序

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

    RestAPI实现聚合

      @Test
    void testAgg() throws IOException {
            //准备request
            SearchRequest request=new SearchRequest("hotel");
            //准备dsl
            request.source().size(0);
            request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(10));
    
            //发送请求
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
    
            //对结果处理
            Aggregations aggregations = search.getAggregations();
            //注意是Terms
            Terms brandAgg = aggregations.get("brandAgg");
            List<? extends Terms.Bucket> buckets = brandAgg.getBuckets();
            //遍历
            for (Terms.Bucket bucket : buckets) {
                String keyAsString = bucket.getKeyAsString();
                System.out.println(keyAsString);
            }
    
    
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    案例:在IUserService中定义方法,实现对品牌、城市、星级的聚合

      @Override
        public Map> agg(RequestParams params) {
            try {
                //获取过滤条件
                //准备request
            SearchRequest request=new SearchRequest("hotel");
            
            //这一部分可以封装为一个函数
          request.source().aggregation(AggregationBuilders.terms("brandAgg").field("brand").size(100));
            request.source().aggregation(AggregationBuilders.terms("cityAgg").field("city").size(100));
            request.source().aggregation(AggregationBuilders.terms("starAgg").field("starName").size(100));
    
            boolQuery(params,request);
    
    
            SearchResponse search = client.search(request, RequestOptions.DEFAULT);
    
            Aggregations aggregations = search.getAggregations();
            Terms brandAgg = aggregations.get("brandAgg");
            Terms cityAgg = aggregations.get("cityAgg");
            Terms starAgg = aggregations.get("starAgg");
    
            List buckets = brandAgg.getBuckets();
            List buckets1 = cityAgg.getBuckets();
            List buckets2 = starAgg.getBuckets();
            List list=new ArrayList<>();
            for (Terms.Bucket bucket : buckets) {
                String keyAsString = bucket.getKeyAsString();
                list.add(keyAsString);
            }
    
            Map> map=new HashMap<>();
            map.put("brand",list);
    
            List list1=new ArrayList<>();
            for (Terms.Bucket bucket : buckets1) {
                String keyAsString = bucket.getKeyAsString();
                list1.add(keyAsString);
            }
            map.put("city",list1);
    
            List list2=new ArrayList<>();
            for (Terms.Bucket bucket : buckets2) {
                String keyAsString = bucket.getKeyAsString();
                list2.add(keyAsString);
            }
            map.put("starName",list2);
    
            return map;
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    测试这个方法

    @SpringBootTest
    class HotelDemoApplicationTests {
    @Autowired
    private HotelService hotelService;
        @Test
        void contextLoads() {
            Map<String, List<String>> filters = hotelService.filters();
            System.out.println(filters);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    实现前端的过滤效果

    在这里插入图片描述

    在IHotelService接口中定义过滤的方法

    Map> filters (RequestParams params);
    
    • 1

    在上面的代码新增参数params

    其中的boolQuery()就是查询实现的过滤

     private static void boolQuery(RequestParams params, SearchRequest request) {
            String key = params.getKey();
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    
            if (key ==null||"".equals(key)){
            //key为空,直接查询所有
    //            request.source().query(QueryBuilders.matchAllQuery());
                boolQueryBuilder.must(QueryBuilders.matchAllQuery());
        }
        else{
    //            request.source().query(QueryBuilders.matchQuery("all",key));
                boolQueryBuilder.must(QueryBuilders.matchQuery("all", key));
        }
    
            //城市
            if (params.getCity()!=null&&!"".equals(params.getCity())){
                boolQueryBuilder.filter(QueryBuilders.termQuery("city", params.getCity()));
            }
            //星级
            if (params.getStarName()!=null&&!"".equals(params.getStarName())){
                boolQueryBuilder.filter(QueryBuilders.termQuery("starName", params.getStarName()));
    
            }
            //品牌
    
            if (params.getBrand()!=null&&!"".equals(params.getBrand())){
                boolQueryBuilder.filter(QueryBuilders.termQuery("brand", params.getBrand()));
            }
            //价格范围
            if (params.getMinPrice()!=null&& params.getMaxPrice()!=null){
                boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(params.getMaxPrice()).gte(params.getMinPrice()));
            }
    
            FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQueryBuilder,new FunctionScoreQueryBuilder.FilterFunctionBuilder[]{
                    new FunctionScoreQueryBuilder.FilterFunctionBuilder(QueryBuilders.termQuery("isAD",true),ScoreFunctionBuilders.weightFactorFunction(10))
            });
    
    
            request.source().query(functionScoreQueryBuilder);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
  • 相关阅读:
    IDEA离线安装插件
    Java高阶数据结构之红黑树
    Python机器视觉--OpenCV进阶(核心)--滤波器之卷积介绍
    设计模式之(9)——适配器 模式
    stm32的时钟、中断的配置(针对寄存器),一些基础知识
    【ASM】字节码操作 转换已有的类 优化 删除复杂的转换 删除加0操作
    【在线聊天】原来微信小程序也能回复Facebook主页消息!
    Linux 下以其他用户运行程序
    redis redisson(仅供自己参考)
    Git-概念与架构
  • 原文地址:https://blog.csdn.net/qq_57907966/article/details/126567418