高峰只对攀登它而不是仰望它的人来说才有真正意义。

如何做两个聚合时,可以按照某个度量值做top10

回复

linyongzhi 发起了问题 • 1 人关注 • 0 个回复 • 4209 次浏览 • 2016-09-22 10:09 • 来自相关话题

关于elasticsearch-analysis-pinyin 关于elasticsearch-analysis-pinyin插件的请教

medcl 回复了问题 • 5 人关注 • 6 个回复 • 4527 次浏览 • 2016-10-13 16:11 • 来自相关话题

ElasticSearch java API - 聚合查询

carlislelee 发表了文章 • 3 个评论 • 53953 次浏览 • 2016-09-20 17:16 • 来自相关话题

以球员信息为例,player索引的player type包含5个字段,姓名,年龄,薪水,球队,场上位置。
index的mapping为:
"mappings": {
"player": {
"properties": {
"name": {
"index": "not_analyzed",
"type": "string"
},
"age": {
"type": "integer"
},
"salary": {
"type": "integer"
},
"team": {
"index": "not_analyzed",
"type": "string"
},
"position": {
"index": "not_analyzed",
"type": "string"
}
},
"_all": {
"enabled": false
}
}
}

索引中的全部数据:

微信截图_20160920171030.png

 
首先,初始化Builder:
SearchRequestBuilder sbuilder = client.prepareSearch("player").setTypes("player");
接下来举例说明各种聚合操作的实现方法,因为在es的api中,多字段上的聚合操作需要用到子聚合(subAggregation),初学者可能找不到方法(网上资料比较少,笔者在这个问题上折腾了两天,最后度了源码才彻底搞清楚T_T),后边会特意说明多字段聚合的实现方法。另外,聚合后的排序也会单独说明。
  • group by/count

例如要计算每个球队的球员数,如果使用SQL语句,应表达如下:
select team, count(*) as player_count from player group by team;
ES的java api:
TermsBuilder teamAgg= AggregationBuilders.terms("player_count ").field("team");
sbuilder.addAggregation(teamAgg);
SearchResponse response = sbuilder.execute().actionGet();
 
  • group by多个field

例如要计算每个球队每个位置的球员数,如果使用SQL语句,应表达如下:
select team, position, count(*) as pos_count from player group by team, position;
ES的java api:
TermsBuilder teamAgg= AggregationBuilders.terms("player_count ").field("team");
TermsBuilder posAgg= AggregationBuilders.terms("pos_count").field("position");
sbuilder.addAggregation(teamAgg.subAggregation(posAgg));
SearchResponse response = sbuilder.execute().actionGet();
 
  • max/min/sum/avg

例如要计算每个球队年龄最大/最小/总/平均的球员年龄,如果使用SQL语句,应表达如下:
select team, max(age) as max_age from player group by team;
ES的java api:
TermsBuilder teamAgg= AggregationBuilders.terms("player_count ").field("team");
MaxBuilder ageAgg= AggregationBuilders.max("max_age").field("age");
sbuilder.addAggregation(teamAgg.subAggregation(ageAgg));
SearchResponse response = sbuilder.execute().actionGet();

  • 对多个field求max/min/sum/avg

例如要计算每个球队球员的平均年龄,同时又要计算总年薪,如果使用SQL语句,应表达如下:
select team, avg(age)as avg_age, sum(salary) as total_salary from player group by team;
ES的java api:
TermsBuilder teamAgg= AggregationBuilders.terms("team");
AvgBuilder ageAgg= AggregationBuilders.avg("avg_age").field("age");
SumBuilder salaryAgg= AggregationBuilders.avg("total_salary ").field("salary");
sbuilder.addAggregation(teamAgg.subAggregation(ageAgg).subAggregation(salaryAgg));
SearchResponse response = sbuilder.execute().actionGet();
 
  • 聚合后对Aggregation结果排序

例如要计算每个球队总年薪,并按照总年薪倒序排列,如果使用SQL语句,应表达如下:
select team, sum(salary) as total_salary from player group by team order by total_salary desc;
ES的java api:
TermsBuilder teamAgg= AggregationBuilders.terms("team").order(Order.aggregation("total_salary ", false);
SumBuilder salaryAgg= AggregationBuilders.avg("total_salary ").field("salary");
sbuilder.addAggregation(teamAgg.subAggregation(salaryAgg));
SearchResponse response = sbuilder.execute().actionGet();
需要特别注意的是,排序是在TermAggregation处执行的,Order.aggregation函数的第一个参数是aggregation的名字,第二个参数是boolean型,true表示正序,false表示倒序。 
  • Aggregation结果条数的问题

默认情况下,search执行后,仅返回10条聚合结果,如果想反悔更多的结果,需要在构建TermsBuilder 时指定size:
TermsBuilder teamAgg= AggregationBuilders.terms("team").size(15);
 
  • Aggregation结果的解析/输出

得到response后:
Map<String, Aggregation> aggMap = response.getAggregations().asMap();
StringTerms teamAgg= (StringTerms) aggMap.get("keywordAgg");
Iterator<Bucket> teamBucketIt = teamAgg.getBuckets().iterator();
while (teamBucketIt .hasNext()) {
Bucket buck = teamBucketIt .next();
//球队名
String team = buck.getKey();
//记录数
long count = buck.getDocCount();
//得到所有子聚合
Map subaggmap = buck.getAggregations().asMap();
//avg值获取方法
double avg_age= ((InternalAvg) subaggmap.get("avg_age")).getValue();
//sum值获取方法
double total_salary = ((InternalSum) subaggmap.get("total_salary")).getValue();
//...
//max/min以此类推
}
 
  • 总结

综上,聚合操作主要是调用了SearchRequestBuilder的addAggregation方法,通常是传入一个TermsBuilder,子聚合调用TermsBuilder的subAggregation方法,可以添加的子聚合有TermsBuilder、SumBuilder、AvgBuilder、MaxBuilder、MinBuilder等常见的聚合操作。
 
从实现上来讲,SearchRequestBuilder在内部保持了一个私有的 SearchSourceBuilder实例, SearchSourceBuilder内部包含一个List<AbstractAggregationBuilder>,每次调用addAggregation时会调用 SearchSourceBuilder实例,添加一个AggregationBuilder。
同样的,TermsBuilder也在内部保持了一个List<AbstractAggregationBuilder>,调用addAggregation方法(来自父类addAggregation)时会添加一个AggregationBuilder。有兴趣的读者也可以阅读源码的实现。
 
如果有什么问题,欢迎一起讨论,如果文中有什么错误,欢迎批评指正。
 
注:文中使用的Elastic Search API版本为2.3.2






 

怎么通过java连接集群中的Node Client节点对集群中索引进行操作?

weizijun 回复了问题 • 2 人关注 • 1 个回复 • 4877 次浏览 • 2016-09-21 12:49 • 来自相关话题

Elasticsearch启动异常

knowmara 回复了问题 • 2 人关注 • 1 个回复 • 16209 次浏览 • 2016-09-20 15:33 • 来自相关话题

查看es正在执行的查询或者以前的查询

weizijun 回复了问题 • 2 人关注 • 1 个回复 • 9501 次浏览 • 2016-09-21 12:51 • 来自相关话题

搜索中文精确问题

martindu 回复了问题 • 2 人关注 • 1 个回复 • 2915 次浏览 • 2016-09-21 16:24 • 来自相关话题

query和filter的速度问题

Xargin 回复了问题 • 6 人关注 • 4 个回复 • 4894 次浏览 • 2016-10-21 12:41 • 来自相关话题

搭建集群后,查询时出现index_out_of_bounds_exception错误?(有很神奇的事情,具体情况内详)

weizijun 回复了问题 • 2 人关注 • 1 个回复 • 9182 次浏览 • 2016-09-21 12:56 • 来自相关话题

ElasticSearch怎么同时对两个字段做sum聚合

weizijun 回复了问题 • 2 人关注 • 1 个回复 • 14269 次浏览 • 2016-09-20 12:35 • 来自相关话题

inner_hits nested bug

回复

lci 发起了问题 • 1 人关注 • 0 个回复 • 4921 次浏览 • 2016-09-19 22:28 • 来自相关话题

Elasticsearch指定routing时,获取操作的分片号

回复

hex2tan 发起了问题 • 1 人关注 • 0 个回复 • 4948 次浏览 • 2016-09-19 11:20 • 来自相关话题

elasticsearch创建快照仓库报错

fhyes123 回复了问题 • 2 人关注 • 1 个回复 • 8013 次浏览 • 2017-05-02 11:34 • 来自相关话题

es hadoop 使用代理连接es服务

回复

seewei 发起了问题 • 1 人关注 • 0 个回复 • 5618 次浏览 • 2016-09-19 10:43 • 来自相关话题

成都地区Elastic中文社区线下活动通知公告!!!

xuchengxi2013 发表了文章 • 1 个评论 • 7880 次浏览 • 2016-09-18 17:16 • 来自相关话题

Elastic中文社区技术沙龙【成都站】即将开始咯!
    Elastic 中文社区联手成都卡莱博尔信息技术股份有限公司共同举办线下技术分享会,欢迎对elastic、搜索引擎、大数据等相关技术感兴趣的朋友来参加。
   卡莱博尔是一家以“大数据、移动智能和认知计算”技术为核心的高新技术企业,公司坐落于成都市高新区天府五街,致力于成为中国高端装备产业大数据应用产品和服务提供商,主要为“国防军工、民用航空、先进船舶、轨道交通、电力能源”等装备行业,提供基于装备运行全生命周期故障预测与健康管理相关的大数据技术支撑和运营服务。
    ElasticSearch(下文简称ES)是当前流行的企业级搜索引擎,它提供了一个分布式多用户能力的全文搜索引擎。大数据时代ES能够提供简单易用的方式帮助企业从大型数据库中快速提取有效信息进行分析。
主办方:elastic中文社区        http://elasticsearch.cn/article/101
协办方:成都卡莱博尔信息技术股份有限公司  http://www.cdcalabar.com
 
海报图标.png


活动信息:
活动时间:2016年10月29日 下午13:00-17:30(本周六)
活动地点:成都市高新区天府软件园E区1栋10楼  成都卡莱博尔信息技术股份有限公司 多功能会议厅
           (活动地点如有变化,会提前通知)
场地容量:60人
活动费用:免费 
交通信息:地铁1号线  天府五街站下车  E区1栋10楼

分享主题:
(1)ES 在多维分析中的使用​  —— 李峰@ logicmonitor    logicmonitor数据平台高级工程师 
                                                     专注于hadoop生态系统相关实数数据的存储计算
(2)ElasticStack V5 新特性与变化   —— Medcl@elastic  Elastic中文社区创始人和布道师
ElasticStack包括Elasticsearch、Logstash、Kibana和Beats,ElasticStack将在过段时间发布一个V5.0全新版本,这次的分享将给大家介绍一下5.0版里面各个产品的一些新的特性和改进。曾勇是Elasticsearch国内首批用户,自2010年起就开始接触Elasticsearch并投入到生产环境中使用,并编写过一系列的中文处理相关的插件,是Elasticsearch中文社区发起人,筹办了一系列线上线下的Elasticsearch技术分享与交流活动,出于对Elasticsearch的喜爱,目前已全职加入Elasticsearch项目背后的Elastic公司。
(3)探究ES的内部存储结构  —— 林添@ logicmonitor    logicmonitor后端高级工程师  
                                   
PPT资料链接:[url=https://github.com/rudyLi/es-chengdu-meetup-share]https://github.com/rudyLi/es-chengdu-meetup-share​[/url] 

报名方式:
 (1)报名连接:http://www.jsform.com/web/form ... fc6a6
 (2)扫描下面微信二维码加入成都Elastic微信群,无法扫描的同学加我微信(xcx_2013),我来拉你进群。电话:15008467351

真诚邀请对elastic技术、搜索引擎技术、大数据存储索引可视化、大数据分析、日志分析等技术感兴趣的朋友前来交流和分享。