文章目录
前言
- 前言
- 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,类似于MySQL的count(distinct field)
- 第一步先将返回的文档中的一个指定的filed进行去重
- 第二步,再统计一下去重后总共有多少条数据;
#cardinality查询
POST /sms-logs-index/_search
{
"aggs": {
"agg": {
"cardinality": {
"field": "province"
}
}
}
}
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:小于
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
}
]
}
}
}
}
#时间范围统计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"
}
}
}
}
@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);
}
关注我的公众号【宝哥大数据】, 更多干货