写点什么

ElasticSearch java API - 聚合查询

  • 2022 年 4 月 14 日
  • 本文字数:2856 字

    阅读完需:约 9 分钟

索引中的全部数据:


<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:


  1. TermsBuilder teamAgg= AggregationBuilders.terms( "player_count ").field( "team");

  2. sbuilder.addAggregation(teamAgg);

  3. 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:


  1. TermsBuilder teamAgg= AggregationBuilders.terms( "player_count ").field( "team");

  2. TermsBuilder posAgg= AggregationBuilders.terms( "pos_count").field( "position");

  3. sbuilder.addAggregation(teamAgg.subAggregation(posAgg));

  4. 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:


  1. TermsBuilder teamAgg= AggregationBuilders.terms( "player_count ").field( "team");

  2. MaxBuilder ageAgg= AggregationBuilders.max( "max_age").field( "age");

  3. sbuilder.addAggregation(teamAgg.subAggregation(ageAgg));

  4. 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:


  1. TermsBuilder teamAgg= AggregationBuilders.terms( "team");

  2. AvgBuilder ageAgg= AggregationBuilders.avg( "avg_age").field( "age");

  3. SumBuilder salaryAgg= AggregationBuilders.avg( "total_salary ").field( "salary");

  4. sbuilder.addAggregation(teamAgg.subAggregation(ageAgg).subAggregation(salaryAgg));

  5. 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:


  1. TermsBuilder teamAgg= AggregationBuilders.terms("team").order(Order.aggregation("total_salary ", false);

  2. SumBuilder salaryAgg= AggregationBuilders.avg("total_salary ").field("salary");

  3. sbuilder.addAggregation(teamAgg.subAggregation(salaryAgg));

  4. 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 后:


  1. <span style= "white-space:pre"> </span Java 开源项目【ali1024.coding.net/public/P7/Java/git】 >Map<String, Aggregation> aggMap = response.getAggregations().asMap();

  2. StringTerms teamAgg= (StringTerms) aggMap.get( "keywordAgg");

  3. Iterator<Bucket> teamBucketIt = teamAgg.getBuckets().iterator();

面试结束复盘查漏补缺

每次面试都是检验自己知识与技术实力的一次机会,面试结束后建议大家及时总结复盘,查漏补缺,然后有针对性地进行学习,既能提高下一场面试的成功概率,还能增加自己的技术知识栈储备,可谓是一举两得。


以下最新总结的阿里 P6 资深 Java 必考题范围和答案,包含最全 MySQL、Redis、Java 并发编程等等面试题和答案,用于参考~


重要的事说三遍,关注+关注+关注!




更多笔记分享



用户头像

还未添加个人签名 2022.04.13 加入

还未添加个人简介

评论

发布
暂无评论
ElasticSearch java API - 聚合查询_Java_爱好编程进阶_InfoQ写作平台