以前总结过metric聚合的内容,本篇来讲一下bucket聚合的知识。Bucket能够理解为一个桶,他会遍历文档中的内容,凡是符合要求的就放入按照要求建立的桶中。数组
好比性别有男、女,就会建立两个桶,分别存放男女的信息。默认会搜集doc_count的信息,即记录有多少男生,有多少女生,而后返回给客户端,这样就完成了一个terms得统计。code
{ "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聚合,结果可能带有必定的误差与错误性。ip
咱们想要获取name字段中出现频率最高的前5个。内存
此时,客户端向ES发送聚合请求,主节点接收到请求后,会向每一个独立的分片发送该请求。
分片独立的计算本身分片上的前5个name,而后返回。当全部的分片结果都返回后,在主节点进行结果的合并,再求出频率最高的前5个,返回给客户端。文档
这样就会形成必定的偏差,好比最后返回的前5个中,有一个叫A的,有50个文档;B有49。 可是因为每一个分片独立的保存信息,信息的分布也是不肯定的。 有可能第一个分片中B的信息有2个,可是没有排到前5,因此没有在最后合并的结果中出现。 这就致使B的总数少计算了2,原本可能排到第一位,却排到了A的后面。 io
为了改善上面的问题,就可使用size和shard_size参数。file
经过这两个参数,若是咱们想要返回前5个,size=5;shard_size能够设置大于5,这样每一个分片返回的词条信息就会增多,相应的偏差概率也会减少。 遍历
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来规定最小的文档数目,只有知足这个参数要求的个数的词条才会被记录返回。
桶聚合也支持脚本的使用:
{ "aggs" : { "genders" : { "terms" : { "script" : "doc['gender'].value" } } } }
以及外部脚本文件:
{ "aggs" : { "genders" : { "terms" : { "script" : { "file": "my_script", "params": { "field": "gender" } } } } } }
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也提供了下面两种方式:
对于子聚合的计算,有两种方式:
默认状况下ES会使用深度优先,不过能够手动设置成广度优先,好比:
{ "aggs" : { "actors" : { "terms" : { "field" : "actors", "size" : 10, "collect_mode" : "breadth_first" }, "aggs" : { "costars" : { "terms" : { "field" : "actors", "size" : 5 } } } } } }
缺省值指定了缺省的字段的处理方式:
{ "aggs" : { "tags" : { "terms" : { "field" : "tags", "missing": "N/A" } } } }