新闻动态
Elasticsearch聚合 之 Terms - xingoo - 博客园
2024-04-28
之前总结过metric聚合的内容,本篇来说一下bucket聚合的知识。Bucket可以理解为一个桶,他会遍历文档中的内容,凡是符合要求的就放入按照要求创建的桶中。
本篇着重讲解的terms聚合,它是按照某个字段中的值来分类:
比如性别有男、女,就会创建两个桶,分别存放男女的信息。默认会搜集doc_count的信息,即记录有多少男生,有多少女生,然后返回给客户端,这样就完成了一个terms得统计。
Terms聚合
{
\"aggs\" : {
\"genders\" : {
\"terms\" : { \"field\" : \"gender\" }
得到的结果如下:
{
\"aggregations\" : {
\"genders\" : {
\"doc_count_error_upper_bound\": 0,
\"sum_other_doc_count\": 0,
\"buckets\" : [
\"key\" : \"male\",
\"doc_count\" : 10
\"key\" : \"female\",
\"doc_count\" : 10
数据的不确定性
使用terms聚合,结果可能带有一定的偏差与错误性。
举个例子:
我们想要获取name字段中出现频率最高的前5个。
此时,客户端向ES发送聚合请求,主节点接收到请求后,会向每个独立的分片发送该请求。
分片独立的计算自己分片上的前5个name,然后返回。当所有的分片结果都返回后,在主节点进行结果的合并,再求出频率最高的前5个,返回给客户端。
这样就会造成一定的误差,比如最后返回的前5个中,有一个叫A的,有50个文档;B有49。
但是由于每个分片独立的保存信息,信息的分布也是不确定的。
有可能第一个分片中B的信息有2个,但是没有排到前5,所以没有在最后合并的结果中出现。
这就导致B的总数少计算了2,本来可能排到第一位,却排到了A的后面。
size与shard_size
为了改善上面的问题,就可以使用size和shard_size参数。
size参数规定了最后返回的term个数(默认是10个)
shard_size参数规定了每个分片上返回的个数
如果shard_size小于size,那么分片也会按照size指定的个数计算
通过这两个参数,如果我们想要返回前5个,size=5;shard_size可以设置大于5,这样每个分片返回的词条信息就会增多,相应的误差几率也会减小。
order排序
order指定了最后返回结果的排序方式,默认是按照doc_count排序。
{
\"aggs\" : {
\"genders\" : {
\"terms\" : {
\"field\" : \"gender\",
\"order\" : { \"_count\" : \"asc\" }
也可以按照字典方式排序:
{
\"aggs\" : {
\"genders\" : {
\"terms\" : {
\"field\" : \"gender\",
\"order\" : { \"_term\" : \"asc\" }
当然也可以通过order指定一个单值的metric聚合,来排序。
{
\"aggs\" : {
\"genders\" : {
\"terms\" : {
\"field\" : \"gender\",
\"order\" : { \"avg_height\" : \"desc\" }
\"aggs\" : {
\"avg_height\" : { \"avg\" : { \"field\" : \"height\" } }
同时也支持多值的Metric聚合,不过要指定使用的多值字段:
{
\"aggs\" : {
\"genders\" : {
\"terms\" : {
\"field\" : \"gender\",
\"order\" : { \"height_stats.avg\" : \"desc\" }
\"aggs\" : {
\"height_stats\" : { \"stats\" : { \"field\" : \"height\" } }
min_doc_count与shard_min_doc_count
聚合的字段可能存在一些频率很低的词条,如果这些词条数目比例很大,那么就会造成很多不必要的计算。
因此可以通过设置min_doc_count和shard_min_doc_count来规定最小的文档数目,只有满足这个参数要求的个数的词条才会被记录返回。
通过名字就可以看出:
min_doc_count:规定了最终结果的筛选
shard_min_doc_count:规定了分片中计算返回时的筛选
script
桶聚合也支持脚本的使用:
{
\"aggs\" : {
\"genders\" : {
\"terms\" : {
\"script\" : \"doc[\'gender\'].value\"
以及外部脚本文件:
{
\"aggs\" : {
\"genders\" : {
\"terms\" : {
\"script\" : {
\"file\": \"my_script\",
\"params\": {
\"field\": \"gender\"
filter
filter字段提供了过滤的功能,使用两种方式:include可以过滤出包含该值的文档;相反则使用exclude。
例如:
{
\"aggs\" : {
\"tags\" : {
\"terms\" : {
\"field\" : \"tags\",
\"include\" : \".*sport.*\",
\"exclude\" : \"water_.*\"
上面的例子中,最后的结果应该包含sport并且不包含water。
也支持数组的方式,定义包含与排除的信息:
{
\"aggs\" : {
\"JapaneseCars\" : {
\"terms\" : {
\"field\" : \"make\",
\"include\" : [\"mazda\", \"honda\"]
\"ActiveCarManufacturers\" : {
\"terms\" : {
\"field\" : \"make\",
\"exclude\" : [\"rover\", \"jensen\"]
多字段聚合
通常情况,terms聚合都是仅针对于一个字段的聚合。因为该聚合是需要把词条放入一个哈希表中,如果多个字段就会造成n^2的内存消耗。
不过,对于多字段,ES也提供了下面两种方式:
1 使用脚本合并字段
2 使用copy_to方法,合并两个字段,创建出一个新的字段,对新字段执行单个字段的聚合。
collect模式
对于子聚合的计算,有两种方式:
depth_first 直接进行子聚合的计算
breadth_first 先计算出当前聚合的结果,针对这个结果在对子聚合进行计算。
默认情况下ES会使用深度优先,不过可以手动设置成广度优先,比如:
{
\"aggs\" : {
\"actors\" : {
\"terms\" : {
\"field\" : \"actors\",
\"size\" : 10,
\"collect_mode\" : \"breadth_first\"
\"aggs\" : {
\"costars\" : {
\"terms\" : {
\"field\" : \"actors\",
\"size\" : 5
缺省值Missing value
缺省值指定了缺省的字段的处理方式:
{
\"aggs\" : {
\"tags\" : {
\"terms\" : {
\"field\" : \"tags\",
\"missing\": \"N/A\"
本文链接: https://www.ebiomall.com/b505-hit2lead/info-1446988186.html
免责声明 本文仅代表作者个人观点,与本网无关。其创作性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不做任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
版权声明 未经蚂蚁淘授权不得转载、摘编或利用其他方式使用上述作品。已经经本网授权使用作品的,应该授权范围内使用,并注明“来源:蚂蚁淘”。违反上述声明者,本网将追究其相关法律责任。
相关文章
2024-01-17
2007-01-16
2012-08-14
2014-09-02
2024-01-19
2015-11-08
2017-01-25
2024-03-15
2024-01-11
▍
品牌问答
暂无品牌问答