elasticsearch聚合之bucketterms聚合
1. 背景
此处简单记录一下 bucket 聚合下的terms 聚合。记录一下terms 聚合的各种用法,以及各种注意事项,防止以后忘记。2. 前置条件2.1 创建索引PUT /index_person { "settings": { "number_of_shards": 1 }, "mappings": { "properties": { "id": { "type": "long" }, "name": { "type": "keyword" }, "sex": { "type": "keyword" }, "age": { "type": "integer" }, "province": { "type": "keyword" }, "address": { "type": "text", "analyzer": "ik_max_word", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } 2.2 准备数据PUT /_bulk {"create":{"_index":"index_person","_id":1}} {"id":1,"name":"张三","sex":"男","age":20,"province":"湖北","address":"湖北省黄冈市罗田县匡河镇"} {"create":{"_index":"index_person","_id":2}} {"id":2,"name":"李四","sex":"男","age":19,"province":"江苏","address":"江苏省南京市"} {"create":{"_index":"index_person","_id":3}} {"id":3,"name":"王武","sex":"女","age":25,"province":"湖北","address":"湖北省武汉市江汉区"} {"create":{"_index":"index_person","_id":4}} {"id":4,"name":"赵六","sex":"女","age":30,"province":"北京","address":"北京市东城区"} {"create":{"_index":"index_person","_id":5}} {"id":5,"name":"钱七","sex":"女","age":16,"province":"北京","address":"北京市西城区"} {"create":{"_index":"index_person","_id":6}} {"id":6,"name":"王八","sex":"女","age":45,"province":"北京","address":"北京市朝阳区"} 3. 各种聚合3.1 统计人数最多的2个省3.1.1 dslGET /index_person/_search { "size": 0, "aggs": { "agg_sex": { "terms": { "field": "province", "size": 2 } } } } 3.1.2 运行结果
运行结果
3.2 统计人数最少的2个省3.2.1 dslGET /index_person/_search { "size": 0, "aggs": { "agg_sex": { "terms": { "field": "province", "size": 2, "order": { "_count": "asc" } } } } }
注意: 不推荐使用 _count:asc 来统计,会导致统计结果不准 ,看下方的总结章节。3.2.2 运行结果
运行结果
3.3 根据字段值排序-根据年龄聚合,返回年龄最小的2个聚合3.3.1 dslGET /index_person/_search { "size": 0, "aggs": { "agg_sex": { "terms": { "field": "age", "size": 2, "order": { "_key": "asc" } } } } }
注意: 这种根据字段值来排序,聚合的结果是正确的。 3.3.2 运行结果
运行结果
3.4 子聚合排序-先根据省聚合,然后根据每个聚合后的最小年龄排序3.4.1 dslGET /index_person/_search { "size": 0, "aggs": { "agg_sex": { "terms": { "field": "province", "order": { "min_age": "asc" } }, "aggs": { "min_age": { "min": { "field": "age" } } } } } } GET /index_person/_search { "size": 0, "aggs": { "agg_sex": { "terms": { "field": "province", "order": { "min_age.min": "asc" } }, "aggs": { "min_age": { "stats": { "field": "age" } } } } } }
注意: 子聚合排序一般也是不准的,但是如果是根据子聚合的 最大值倒序 和最小值升序 又是准的。3.4.2 运行结果
运行结果
3.5 脚本聚合-根据省聚合,如果地址中有黄冈市则需要出现黄冈市
3.5.1 dsl
GET /index_person/_search { "size": 0, "runtime_mappings": { "province_sex": { "type": "keyword", "script": """ String province = doc["province"].value; String address = doc["address.keyword"].value; if(address.contains("黄冈市")){ emit("黄冈市"); }else{ emit(province); } """ } }, "aggs": { "agg_sex": { "terms": { "field": "province_sex" } } } }
注意事项
3.5.2 运行结果
运行结果
3.6 filter-以省分组,并且只包含北的省,但是需要排除湖北省3.6.1 dslGET /index_person/_search { "size": 0, "aggs": { "agg_province": { "terms": { "field": "province", "include": ".*北.*", "exclude": ["湖北"] } } } }
注意: 当是字符串时,可以写正则表达式,当是数组时,需要写具体的值。 3.6.2 运行结果
运行结果
3.7 多term聚合-根据省和性别聚合,然后根据最大年龄倒序3.7.1 dslGET /index_person/_search { "size": 0, "aggs": { "genres_and_products": { "multi_terms": { "size": 10, "shard_size": 25, "order":{ "max_age": "desc" }, "terms": [ { "field": "province", "missing": "defaultProvince" }, { "field": "sex" } ] }, "aggs": { "max_age": { "max": { "field": "age" } } } } } }
注意: terms 聚合默认不支持多字段聚合,需要借助别的方式。此处使用multi terms 来实现多字段聚合。3.7.2 运行结果
运行结果
3.8 missing value 处理
missing value 处理
3.9 多个聚合-同时返回根据省聚合和根据性别聚合
3.9.1 dsl
GET /index_person/_search { "size": 0, "aggs": { "agg_province": { "terms": { "field": "province" } }, "agg_sex":{ "terms": { "field": "sex", "size": 10 } } } }
3.9.2 运行结果
运行结果
4. 总结
4.1 可以聚合的字段
一般情况下,只有如下几种字段类型可以进行聚合操作 keyword ,numeric ,ip ,boolean 和binary 类型的字段。text 类型的字段默认情况下是不可以进行聚合的,如果需要聚合,需要开启fielddata 。
可以聚合的字段
4.2 如果我们想返回所有的聚合Term结果
如果我们只想返回 100 或1000 个唯一结果,可以增大size 参数的值。但是如果我们想返回所有的,那么推荐使用 composite aggregation
如果我们想返回所有的聚合Term结果4.3 聚合数据不准
我们通过 terms 聚合到的结果是一个大概的结果,不一定是完全正确的。
为什么? . 举个例子: 如果我们的集群有3个分片,此处我们想返回值最高的5个统计。即size=5 ,假设先不考虑shard_size 参数,那么此时每个节点会返回值最高的5个统计,然后再次聚合,返回,返回最终值最高的5个。这个貌似没什么问题,但是因为我们的数据是分布es的各个节点上的,可能某个统计项(北京市的用户数 ),在A节点是是排名前5,但是在B节点上不是排名前5,那么最终的统计结果是否是就会漏统计了。
如何解决: 我们可以让es在每个节点上多返回几个结果,比如 :我们的size=5 ,那么我们每个节点就返回 size * 1.5 + 10 个结果,那么误差相应的就会减少。 而这个size * 1.5 + 10 就是shard_size 的值,当然我们也可以手动指定,但一般需要比size的值大。
聚合数据不准
4.4 排序注意事项
4.4.1 _count 排序
默认情况下,使用的是 _count 倒序的,但是我们可以指定成升序,但是这是不推荐的,会导致错误结果。如果我们想要升序,可以使用 rare_terms 聚合。
_count 排序
4.4.2 字段值排序
使用字段值排序,不管是正序还是倒序,结果是准确的。
字段值排序
4.4.3 子聚合排序
子聚合排序
4.5 多term聚合
多term聚合
5、源码地址
https://gitee.com/huan1993/spring-cloud-parent/blob/master/es/es8-api/src/main/java/com/huan/es8/aggregations/bucket/TermsAggs.java 6. 参考链接https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-multi-terms-aggregation.html
家乐福购物卡使用受限遭质疑!顾客吐槽货架空了,物价高了近期家乐福购物卡在门店无法购物消息持续发酵多地消费者反映使用家乐福购物卡消费受限部分家乐福门店货架出现空置现象作为首批进入中国的国外大型商场家乐福曾被业界称为零售之王如今传统大卖场
保罗克鲁格曼经济学家为什么错得如此离谱?原创李井奎按此文克鲁格曼写于2008年大危机之后,题目中的经济学家其实是特指自20世纪80年代以来的宏观经济学家,具体来说,就是研究经济波动的一批主流经济学者。不过,此文中的许多批
海口数字赋能产业兴,点亮发展新引擎当前,数字经济已成为重塑产业经济结构增强区域竞争力的关键力量和重要方向。2022年,海口数字经济营收575。32亿元(不含商贸业)。全市新增注册互联网企业数量2278家,累计达21
前沿腾讯研究院发布2023年十大数字科技前沿应用趋势腾讯研究院联合百位内部科学家技术专家和外部院士专家,发布升维2023年十大数字科技前沿应用趋势报告观察。报告从数字科技的科研突破重大事件和创新应用等方面,对高性能计算泛在操作系统云
长安汽车重构乘用车品牌架构,特斯拉股价一周大涨33第一财经汽车日评长安汽车重构乘用车品牌架构近日,长安汽车在重庆举办全球伙伴大会。本次会议上,长安汽车正式发布了新序列OX未来规划,同时发布了智电iDD和3款电混车型。长安汽车董事长朱华荣表示,长安
回忆旧年时间太瘦,指缝太宽,握不住也抓不牢的生命辰光就这样在我的满腹唏嘘中,在我万分无奈中溜走。2022,一个充满了艰难与期盼的年轮,一个让我顿足又失落的一年。这一年我颇有感慨,我总想把一
烟火,中国一场烟火,别人只记得它的壮美。一个中国人只记得它雄伟。一点火苗从线头到线尾线头烧光了,这时就会喷出火花是多么好看啊!一点一点就像一个喷泉五光十色,在夜里是多闪亮,好像喷出来的不是火
想走的路,永远不远想走的路,永远不远。怎料,自己竟被一位五十多岁,没有在学校待过一天的大妈的一句话破防了。绵延不绝的爆竹声拉开了新年的帷幕,破开了新年的气象。望着点点繁星,看着灿烂的烟花,家乡的味道
金句摘抄少年歌行太燃了!伞,遮得了天上的雨,却遮不住心里的雨,我们索性把心灵洗一洗,总会雨过天晴,云淡风轻。佛哭了,魔笑了,魔说该渡的你不渡,不该渡的你偏渡,既然佛不渡你,那就魔来护你。师傅没教我念经,没
三体粒子对撞实验三体动画的一开头就有这样的台词科学发展,突破口在哪儿?粒子对撞实验?!接下来我们就看到了太空中的对撞机当然也看到了智子对实验的干扰。三体人为何如此害怕地球人的对撞机?对撞机实际上是
知名投资人林劲峰做客徽商商海经分享投资逻辑投资最好的建议就是不要盲目听取别人的建议,投资最大的风口就是远离风口。林劲峰盈信投资集团董事长林劲峰(右)接受徽商商海经栏目专访2023年1月5日,由中国农业银行安徽省分行独家冠名