ElasticSearch java API - 聚合查询
索引中的全部数据:
<table cellspacing="0" cellpadding="0" border="1" style="border-spacing:0px;width:361px;table-layout:fixed;border:1px solid rgb(204,204,204);"><tbody><tr><td style="width:81px;">name</td><td style="width:70px;">age</td><td style="width:70px;">salary</td><td style="width:70px;">team</td><td style="width:70px;">position</td></tr><tr><td style="width:81px;">james</td><td style="width:70px;">33</td><td style="width:70px;">3000</td><td style="width:70px;">cav</td><td style="width:70px;">sf</td></tr><tr><td style="width:81px;">irving</td><td style="width:70px;">25</td><td style="width:70px;">2000</td><td style="width:70px;">cav</td><td style="width:70px;">pg</td></tr><tr><td style="width:81px;">curry</td><td style="width:70px;">29</td><td style="width:70px;">1000</td><td style="width:70px;">war</td><td style="width:70px;">pg</td></tr><tr><td style="width:81px;">thompson</td><td style="width:70px;">26</td><td style="width:70px;">2000</td><td style="width:70px;">war</td><td style="width:70px;">sg</td></tr><tr><td style="width:81px;">green</td><td style="width:70px;">26</td><td style="width:70px;">2000</td><td style="width:70px;">war</td><td style="width:70px;">pf</td></tr><tr><td style="width:81px;">garnett</td><td style="width:70px;">40</td><td style="width:70px;">1000</td><td style="width:70px;">tim</td><td style="width:70px;">pf</td></tr><tr><td style="width:81px;">towns</td><td style="width:70px;">21</td><td style="width:70px;">500</td><td style="width:70px;">tim</td><td style="width:70px;">c</td></tr><tr><td style="width:81px;">lavin</td><td style="width:70px;">21</td><td style="width:70px;">300</td><td style="width:70px;">tim</td><td style="width:70px;">sg</td></tr><tr><td style="width:81px;">wigins</td><td style="width:70px;">20</td><td style="width:70px;">500</td><td style="width:70px;">tim</td><td style="width:70px;">sf</td></tr></tbody></table>
首先,初始化 Builder:
SearchRequestBuilder sbuilder = client.prepareSearch("player").setTypes("player");
接下来举例说明各种聚合操作的实现方法,因为在 es 的 api 中,多字段上的聚合操作需要用到子聚合(subAggregation),初学者可能找不到方法(网上资料比较少,笔者在这个问题上折腾了两天,最后度了源码才彻底搞清楚 T_T),后边会特意说明多字段聚合的实现方法。另外,聚合后的排序也会单独说明。
[](()1. group by/count
例如要计算每个球队的球员数,如果使用 SQL 语句,应表达如下 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 :
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();
[](()2.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();
[](()3.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();
[](()4.对多个 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();
[](()5.聚合后对 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 表示倒序。
[](()6.Aggregation 结果条数的问题
默认情况下,search 执行后,仅返回 10 条聚合结果,如果想反悔更多的结果,需要在构建 TermsBuilder 时指定 size:
TermsBuilder teamAgg= AggregationBuilders.terms("team").size(15);
[](()7.Aggregation 结果的解析/输出
得到 response 后:
<span style= "white-space:pre"> </span Java 开源项目【ali1024.coding.net/public/P7/Java/git】 >Map<String, Aggregation> aggMap = response.getAggregations().asMap();
StringTerms teamAgg= (StringTerms) aggMap.get( "keywordAgg");
Iterator<Bucket> teamBucketIt = teamAgg.getBuckets().iterator();
面试结束复盘查漏补缺
每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。
以下最新总结的阿里 P6 资深 Java 必考题范围和答案,包含最全 MySQL、Redis、Java 并发编程等等面试题和答案,用于参考~
重要的事说三遍,关注+关注+关注!
更多笔记分享
评论