您当前的位置: 首页 > 

宝哥大数据

暂无认证

  • 1浏览

    0关注

    1029博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

ES--聚合查询

宝哥大数据 发布时间:2021-03-31 17:30:23 ,浏览量:1

文章目录
  • 前言
    • Elasticsearch将聚合分为三类:
  • 一、cardinality(去重计数)查询
    • 1.1、依据province字段查询所有公司驻场在几个城市,即去重province后,最终有几个城市。
      • 1.1.1、RESTful 代码
        • 1.1.1.1、注意: 不适合需要精确去重场景
      • 1.1.2、java 代码
  • 二、range(范围统计)查询
    • 2.1、案例
      • 2.1.1、依据`fee`字段查询费用小于200的;大于等于200,小于400;大于等于400的分别有多少公司
      • 2.1.2、依据createDate字段创建日期小于2020-09-17和大于等于2020-09-17到至今(2020-10-12)的文档数据分别有多少公司
      • 2.1.3、依据ipAddr字段ip网段小于10.126.2.8和大于等于10.126.2.8的文档数据分别有多少公司
      • 2.1.4、java 代码实现
  • 三、extended_stats(统计聚合)查询
    • 3.1、实例:依据fee字段查询最大值,最小值,平均值,平方和等
      • 3.1.1、RESTful 代码
      • 3.1.2、java 代码
  • 关注我的公众号【宝哥大数据】, 更多干货

前言

ES的聚合查询和MySQL的聚合查询类型类似,但是ES的聚合查询相比于MySQL要强大的多,ES提供的统计数据的方式多种多样,这里就挑选几个常用的来示范一下,更多的内容可以参考官网Aggregations;

ES聚合查询的RESTFul代码语法如下;

POST /index/_search   #这里和普通查询一样,一般用POST或者GET,后面接索引名和_search,用/隔开
{
	"aggs":{       #这里和普通的query不一样了,不是写query,是写aggs,是aggregations的缩写               
	    "名字,一般用agg":  #这里指定此次聚合计算的一个名字,一般都起名agg
	    {
	        "agg_type":  #选择系统内的聚合函数类型
	        {
	            "属性":"值"   #指定需要聚合计算的属性和值
	        }
	    }
	}
}


Elasticsearch将聚合分为三类:
  • Metric aggregations that calculate metrics, such as a sum or average, from field values.
  • Bucket aggregations that group documents into buckets, also called bins, based on field values, ranges, or other criteria.
  • Pipeline aggregations that take input from other aggregations instead of documents or fields.
一、cardinality(去重计数)查询

去重计算,即cardinality,类似于MySQL的count(distinct field)

  • 第一步先将返回的文档中的一个指定的filed进行去重
  • 第二步,再统计一下去重后总共有多少条数据;
1.1、依据province字段查询所有公司驻场在几个城市,即去重province后,最终有几个城市。 1.1.1、RESTful 代码
#cardinality查询
POST /sms-logs-index/_search
{
  "aggs": {
    "agg": {
      "cardinality": {
        "field": "province"
      }
    }
  }
}


在这里插入图片描述

1.1.1.1、注意: 不适合需要精确去重场景

cardinality的优点性能快,亿级别的记录在1秒内完成,但是存在只能保证最大40000条记录内的精确,超过的存在5%的误差,不适合需要精确去重场景!参数precision_threshold接受 0–40000 之间的数字,更大的值还是会被当作 40000 来处理。precision_threshold值设置的越大,占用内存越大,样例如下;

GET /myindex/mytype/_search
{
    "size" : 0,
    "aggs" : {
        "distinct_idCard" : {
            "cardinality" : {
              "field" : "idCard",
              "precision_threshold" : 100 
            }
        }
    }
}

1.1.2、java 代码
package com.chb.test;

import com.chb.utils.ESClient;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.metrics.Cardinality;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.Test;

import java.io.IOException;

import static com.chb.test.ScrollDemo.myClient;

public class AggDemo {
    RestHighLevelClient client = ESClient.getClient();
    String index = "sms-logs-index";

    @Test
    public void cardnality() throws IOException {
        //1.SearchRequest
        SearchRequest request = new SearchRequest(index);

        //2.聚合查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.aggregation(AggregationBuilders.cardinality("agg").field("province"));
        request.source(builder);

        //3.执行查询
        SearchResponse resp = myClient.search(request, RequestOptions.DEFAULT);

        //4.返回结果,默认返回的是父类Aggregation
        Aggregation agg = resp.getAggregations().get("agg");

        //转换成子接口Cardinality才有getValue()方法,父接口Aggregation没有该方法
        Cardinality myagg = (Cardinality) agg;

        //以上两句代码也可以写成直接写成    Cardinality agg = resp.getAggregations().get("agg");
        //后续所有的聚合查询都要有此类似的操作,切记!

        long value = myagg.getValue();
        System.out.println(value);
    }
}

二、range(范围统计)查询

统计一定范围内出现的文档个数,比如。针对某一个field的值在0到100,100到200,200到300之间的文档出现的个数分别是多少。 范围统计可以针对普通的数值,针对时间,针对ip类型都可以做相应的统计。 range,date_range,ip_range range统计这里涉及参数:

  • from:大于等于
  • to:小于
2.1、案例 2.1.1、依据fee字段查询费用小于200的;大于等于200,小于400;大于等于400的分别有多少公司
# range
POST /sms-logs-index/_search
{
  "aggs": {
    "rangeAgg": {
      "range": {
        "field": "fee",
        "ranges": [
          {
            "to": 200
          },
                    {
            "from": 200,
            "to": 400
          },
          {
            "from": 400
          }
        ]
      }
    }
  }
}


在这里插入图片描述

2.1.2、依据createDate字段创建日期小于2020-09-17和大于等于2020-09-17到至今(2020-10-12)的文档数据分别有多少公司
#时间范围统计date_range
POST /sms-logs-index/_search
{
  "aggs": {
    "agg": {
      "date_range": {
        "field": "createDate",
        "format": "yyyy-MM-dd", 
        "ranges": [
          {
            "to": "2020-09-17"
          },
          {
            "from": "2020-09-17",
            "to": "now"
          }
        ]
      }
    }
  }
}

2.1.3、依据ipAddr字段ip网段小于10.126.2.8和大于等于10.126.2.8的文档数据分别有多少公司
POST /sms-logs-index/_search
{
  "aggs": {
    "agg": {
      "ip_range": {
        "field": "ipAddr",
        "ranges": [
          {
            "to": "10.126.2.8"
          },
          {
            "from": "10.126.2.8"
          }
        ]
      }
    }
  }
}

2.1.4、java 代码实现
    @Test
    public void range() throws IOException {
        //1.SearchRequest
        SearchRequest request=new SearchRequest(index);

        //2.聚合查询条件
        SearchSourceBuilder builder=new SearchSourceBuilder();
        // AggregationBuilders
        builder.aggregation(AggregationBuilders.range("agg").field("fee").addUnboundedTo(200).addRange(200,400).addUnboundedFrom(400));
        request.source(builder);

        //3.执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4.返回结果,默认返回的是父类Aggregation
        Range agg = resp.getAggregations().get("agg");
        for (Range.Bucket bucket : agg.getBuckets()) {
            String key=bucket.getKeyAsString();
            Object from = bucket.getFrom();
            Object to = bucket.getTo();
            long docCount = bucket.getDocCount();

            System.out.println(String.format("key:%s,from:%s,to,%s,docCount:%s",key,from,to,docCount));
        }
    }
三、extended_stats(统计聚合)查询

可以帮你指定field的最大值,最小值,平均值,平方和等

3.1、实例:依据fee字段查询最大值,最小值,平均值,平方和等 3.1.1、RESTful 代码
POST /sms-logs-index/_search
{
  "aggs": {
    "aggE": {
      "extended_stats": {
        "field": "fee"
      }
    }
  }
}

在这里插入图片描述

3.1.2、java 代码
    @Test
    public void extended_stats() throws IOException {
        //1.SearchRequest
        SearchRequest request=new SearchRequest(index);

        //2.聚合查询条件
        SearchSourceBuilder builder=new SearchSourceBuilder();
        builder.aggregation(AggregationBuilders.extendedStats("agg").field("fee"));
        request.source(builder);

        //3.执行查询
        SearchResponse resp = client.search(request, RequestOptions.DEFAULT);

        //4.返回结果,默认返回的是父类Aggregation
        ExtendedStats agg=resp.getAggregations().get("agg");

        double max = agg.getMax();
        double min = agg.getMin();

        //其他的属性就不一一例举了

        System.out.println("max fee :  "+max+"  min fee :  "+min);
    }
关注我的公众号【宝哥大数据】, 更多干货

在这里插入图片描述

关注
打赏
1587549273
查看更多评论
立即登录/注册

微信扫码登录

0.0422s