Elasticsearch-2.4.x > Aggregations > Bucket Aggregations > Terms Aggregation

Terms聚合

一个基于multi-bucket值的聚合,其中bucket是动态构建的-每个唯一值一个桶
Example:

{
    "aggs" : {
        "genres" : {
            "terms" : { "field" : "genre" }
        }
    }
}

Response:

{
    ...

    "aggregations" : {
        "genres" : {
            "doc_count_error_upper_bound": 0,                                     (1)
            "sum_other_doc_count": 0,                                             (2)
            "buckets" : [                                                         (3)
                {
                    "key" : "jazz",
                    "doc_count" : 10
                },
                {
                    "key" : "rock",
                    "doc_count" : 10
                },
                {
                    "key" : "electronic",
                    "doc_count" : 10
                },
            ]
        }
    }
}

(1) 文档上的错误的上限对每一个term都有影响.看下面
(2) 当有很多的唯一term时,elasticsearch只会返回前几个term(默认是10),这个数字是没有响应部分的全部桶的文档计数总和.
(3) top buckets的列表,top顺序是由order定义的.

默认情况下,terms aggregation将会返回通过doc_count降序排列后的前十个term的桶.可以通过设置size参数大小来改变这种默认行为.

Size

可以设置size参数来定义从全部的terms list中返回多少个term bucket.默认情况下,协调搜索过程的节点将请求每一个分片使其提供自己的top size term buckets.一旦所有的分片相应,协调节点将会对每个shard的结果合并重新排序,取top size term buckets.然后返回给客户端.这就意味着如果term buckets的数量大于size参数,返回的列表是不准确的(可能是term计数有点偏差,甚至可能是本应该在top size term buckets中的但没有返回).

warning : Deprecated in 2.4.0
size设置为0,则会默认将size设置为integer.MAX_VALUE,已经废弃.并且将会在下一个主要的版本中移除.

文档数是近似的

综上所述,terms agg的文档计数(以及任何子聚合的结果)不总是准确的.这是因为每一个分片提供自己的视图来显示terms有哪些,然后将它们合并起来给出最终的视图.考虑以下场景:

请求获取字段product中的前5个term,按照三个分片的文档计数排序,要求每个shard给出它的前5个term.

{
    "aggs" : {
        "products" : {
            "terms" : {
                "field" : "product",
                "size" : 5
            }
        }
    }
}

三个shard的term如下:

-shard Ashard Bshard C
1Product A (25)Product A (30)Product A (45)
2Product B (18)Product B (25)Product C (44)
3Product C (6)Product F (17)Product Z (36)
4Product D (3)Product Z (16)Product G (30)
5Product E (2)Product G (15)Product E (29)
6Product F (2)Product H (14)Product H (28)
7Product G (2)Product I (10)Product Q (2)
8Product H (2)Product Q (6)Product D (1)
9Product I (1)Product J (8)
10Product J (1)Product C (4)

shard返回前5个term,所以每个shard的结果为:

-shard Ashard Bshard C
1Product A (25)Product A (30)Product A (45)
2Product B (18)Product B (25)Product C (44)
3Product C (6)Product F (17)Product Z (36)
4Product D (3)Product Z (16)Product G (30)
5Product E (2)Product G (15)Product E (29)

从每个shard中选取前5个term,并将它们组合成最后的前5个term,得到一下结果:

-final result
1Product A (100)
2Product Z (52)
3Product C (50)
4Product G (45)
5Product B (43)

因为Product A是从所有分片中返回的,所以它的计数是准确的.Product C 只有 shard A 和 C 返回,所以它的计数是50,但不是准确的计数.Product C存在于shard B中,但其计数4排名不够高,无法将Product C放入该shard的前5个term中.Product Z 也只返回2个shard,但是第三个shard中不包含该term.没有办法知道文档中有一个错误计数Product C而不是Product Z.Product H的计数44在三个shard中,但没有在最终的名单上,因为它没有进入每个shard的前五.

Shard Size

请求的大小越高(size越大),结果更准确,但同时,计算最终的结果成本越高(一方面在shard级别上管理的优先级队列更大,另一方面是节点和客户机之间的数据传输更大).
shard_size参数可以控制每个shard的优先级队列大小,一旦所有的shard响应,协调节点将减少它们的最终结果基于size参数,这种方式,可以增加返回条件的准确性,避免了a big list of buckets返回给客户端.

note: shard_size的值小于size是没有意义的.如果这样设置了,elasticsearch会重置shard_size的值为size的值大小.

默认shard_size的值是size参数的倍数.这依赖于分片的数量.

计算文档计数错误

有两个错误在terms agg中显示,第一个给出了聚合作为一个整体的值,它代表了一个term的最大潜在文档数,但这个term最终没有出现在最终的term列表中.这个是计算每个shard返回的最后一项的文档计数总和.对于上面给出的例子,该值将是46(2+15+29).这意味着最坏的情况是,没有返回的term可以拥有第4高的文档计数.

{
    ...

    "aggregations" : {
        "products" : {
            "doc_count_error_upper_bound" : 46,
            "buckets" : [
                {
                    "key" : "Product A",
                    "doc_count" : 100
                },
                {
                    "key" : "Product Z",
                    "doc_count" : 52
                },
                ...
            ]
        }
    }
}

每个桶文档计数错误

第二个错误值可以通过将show_term_doc_count_error设置为true来启用.这显示了聚合返回的每个term的错误值,该值表示term的文档计数的最坏情况,可以通过此值来决定shard_size的参数是否针对该term有用.计算方法是将所有没有返回该term的shard返回的最后一个term计数相加.在上面的例子中,Product C的文档计数中的错误值将是15,因为Shard B是唯一一个不返回该term的shard,而最后的一个term的计数是15.Product C实际的文档计数是54,而没有在最终列表中的Product C的文档计数是4,最坏的情况是15.Product A 的文档计数的错误值为0,因为每个shard都返回它,所以它的文档计数是准确的.

{
    ...

    "aggregations" : {
        "products" : {
            "doc_count_error_upper_bound" : 46,
            "buckets" : [
                {
                    "key" : "Product A",
                    "doc_count" : 100,
                    "doc_count_error_upper_bound" : 0
                },
                {
                    "key" : "Product Z",
                    "doc_count" : 52,
                    "doc_count_error_upper_bound" : 2
                },
                ...
            ]
        }
    }
}

这些错误值只能在doc_count降序排列的情况下计算,当聚合按照term本身(升序或降序)排序时,文档计数中没有错误.这是因为一个term在一个shard中返回而在另一个shard中没有返回,那么该term要么不会出现在最终列表中,要么该shard中的不包含该term.当聚合按子聚合或按升序文档计数排序时,无法确定文档计数中的错误,并给出一个值-1来表示这一点.

排序

可以通过设置order参数来指定桶的顺序.默认情况下,这些bucket是由它们的doc_count降序排列的.可以改变如下所示的行为:

通过升序_count或子聚合排序是不允许的,因为这会增加文档计数的错误.查询一个shard是可以的,或当被聚合的字段在索引时用作路由键时,在这种情况下结果是准确的,因为shard不具有相交的term.否则,错误将是无限大的.一个仍然有用的特殊情况是通过min agg和max agg排序.计数不是准确的,但至少最上面的桶将被正确的挑选.

按照doc_count升序方式排序桶

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "_count" : "asc" }
            }
        }
    }
}

按照term的字母顺序升序排序桶

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "_term" : "asc" }
            }
        }
    }
}

通过单值度量子聚合(通过聚合名称标识)排序桶

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "avg_play_count" : "desc" }
            },
            "aggs" : {
                "avg_play_count" : { "avg" : { "field" : "play_count" } }
            }
        }
    }
}

通过多值度量子聚合(通过聚合名称标识)排序桶

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "order" : { "playback_stats.avg" : "desc" }
            },
            "aggs" : {
                "playback_stats" : { "stats" : { "field" : "play_count" } }
            }
        }
    }
}

warning: pipeline agg 不能用于排序
在其他聚合完成后,pipeline agg将在reduce阶段运行.由于这个原因,它不能用于排序.

还可以根据层次结构中的”更深层次”聚合来排序bucket,只要agg path是single-bucket类型,就支持这种排序.路径中的最后一个聚合可以是single-bucket聚合也可以是度量聚合.如果是single-bucket聚合,顺序将由doc_count来定义.如果是度量聚合,则使用和上面相同的规则(在多值度量聚合的情况下,路径必须指定要排序的度量名称,而在单值度量聚合的情况下,排序将应用该值)

路径必须以以下形式定义:

AGG_SEPARATOR       =  '>' ;
METRIC_SEPARATOR    =  '.' ;
AGG_NAME            =  <the name of the aggregation> ;
METRIC              =  <the name of the metric (in case of multi-value metrics aggregation)> ;
PATH                =  <AGG_NAME> [ <AGG_SEPARATOR>, <AGG_NAME> ]* [ <METRIC_SEPARATOR>, <METRIC> ] ;
{
    "aggs" : {
        "countries" : {
            "terms" : {
                "field" : "artist.country",
                "order" : { "rock>playback_stats.avg" : "desc" }
            },
            "aggs" : {
                "rock" : {
                    "filter" : { "term" : { "genre" : "rock" }},
                    "aggs" : { "playback_stats" : { "stats" : { "field" : "play_count" }} } }
            }
        }
    }
}

上面根据摇滚歌曲的平均播放次数对artist.country进行降序排列.

可以使用多个标准来排序桶,方法是提供一系列的顺序标准,如下

{
    "aggs" : {
        "countries" : {
            "terms" : {
                "field" : "artist.country",
                "order" : [ { "rock>playback_stats.avg" : "desc" }, { "_count" : "desc" } ]
            },
            "aggs" : {
                "rock" : {
                    "filter" : { "term" : { "genre" : { "rock" }}},
                    "aggs" : {
                        "playback_stats" : { "stats" : { "field" : "play_count" }}
                    }
                }
            }
        }
    }
}

上面将根据摇滚歌曲的平均播放次数以及atrist.country的doc_count(降序排列)对artist.country进行排序.

waring : 如果两个桶的排序值是相同的,则按照桶的term字母顺序升序排列,防止桶的不确定性排序.

最小文档计数

可以通过min_doc_count设置文档数目最小匹配项.

{
    "aggs" : {
        "tags" : {
            "terms" : {
                "field" : "tags",
                "min_doc_count": 10
            }
        }
    }
}

上述聚合只返回文档计数>=10的term.默认值为1.

term在shard级别上被收集和排序,然后合并其他shard中收集的term.但是,shard中没有全局文档计数的信息.是否将一个term添加到候选列表取决于使用本地shard频率该term在shard上的计算顺序.min_doc_count只有在合并完所有shard的本地term统计信息后才使用.在某种程度上,决定将该term添加为候选者,而不是非常确定该term是否实际达到所需的min_doc_count.如果低频率term填充候选列表,这可能导致结果中缺少许多(全局)高频率term.为避免这种情况,可以增加shard_size参数以允许分片上有更多的候选term,但是,这会增加内存消耗和网络流量.

shard_min_doc_count 参数

参数shard_min_doc_count调整了切分shard的确定性,如果该term实际上应该被添加到候选列表中,或者不应该被添加到min_doc_count中.只有当该term在本地shard频率高于shard_min_cod_count时才会被考虑.如果你的字典中包含了许多低频词并且你不感兴趣.(例如拼写错误),可以设置shard_min_doc_count参数过滤term,即使合并本地计算,过滤的term也不会达到所需的min_doc_count.shard_min_doc_count每个默认值设置为0,除非显式的设置,否则它没有任何效果.

note: 设置min_doc_count=0也会为没有匹配的命中term返回bucket.但是,一些返回文档计数为0的term可能只属于被删除的文档或者来自其他类型的文档,因此不保证match_all查询会发现这些term的文档计数为正数

-

warning: 当不对doc_count降序排列时,min_doc_count的高值可能会返回一些桶,但这些桶的大小小于size,因为从shard中收集的数据不足导致的.可以通过增加shard_size恢复丢失的bucket.设置shard_min_doc_count过高将导致在shard级别上过滤term.这个值应该设置得比min_doc_count低得多.

脚本

使用脚本生成terms:

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "script" : "doc['genre'].value"
            }
        }
    }
}

这把script参数解释为使用默认脚本语言而没有脚本参数的inline脚本.要使用file script,使用以下语法:

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "script" : {
                    "file": "my_script",
                    "params": { "field": "genre" } }
            }
        }
    }
}

tip: 对于索引脚本,用id代替file.

值的脚本

{
    "aggs" : {
        "genres" : {
            "terms" : {
                "field" : "genre",
                "script" : "'Genre: ' +_value"
            }
        }
    }
}

过滤值

可以对将要创建的bucket的值进行筛选。这可以使用include和exclude参数来完成,这些参数基于正则表达式字符串或精确值数组。

{
    "aggs" : {
        "tags" : {
            "terms" : {
                "field" : "tags",
                "include" : ".*sport.*",
                "exclude" : "water_.*"
            }
        }
    }
}

在上面的例子中,除了以water_开头的标签(因此不会聚合标记water_sports)之外,所有包含sport这个单词的标签都将创建bucket。include正则表达式将确定“允许”聚合哪些值,而exclude将确定不应该聚合的值。当两个都被定义时,exclude有优先级,也就是说,首先计算include,然后才计算exclude。

为了基于精确的值进行匹配,include和exclude参数可以简单地使用字符串数组来表示在索引中找到的term:

{
    "aggs" : {
        "JapaneseCars" : {
             "terms" : {
                 "field" : "make",
                 "include" : ["mazda", "honda"]
             }
         },
        "ActiveCarManufacturers" : {
             "terms" : {
                 "field" : "make",
                 "exclude" : ["rover", "jensen"]
             }
         }
    }
}

Multi-field terms 聚合

terms 聚合不支持从同一文档中的多个字段收集term.原因是terms agg本身不收集字符串term.而是使用全局序号生成字段中所有唯一值的列表.全局序号会带来重要的性能提升,而在多个字段之间是不可能实现的.

有两种方法可用于跨多个字段执行terms agg:

脚本
使用脚本从多个字段检索term。这将禁用全局序号优化,并且比从单个字段中收集term要慢,但是它提供了在搜索时实现此选项的灵活性。

copy_to field
如果事先知道要从两个或多个字段收集term,那么在映射中使用copy_to在索引时创建一个新的专用字段,该字段包含两个字段的值。您可以在这个单一字段上进行聚合,这将从全局序号优化中获益。

收集模式

执行提示

缺失值

缺失的参数定义了如何处理缺失值的文档。默认情况下,它们将被忽略,但也可以将它们视为有值。

{
    "aggs" : {
        "tags" : {
             "terms" : {
                 "field" : "tags",
                 "missing": "N/A"                                                          (1)
             }
         }
    }
}

(1) 在tags字段中没有值的文档将与值为N/ a的文档归入同一类别。

官网:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/search-aggregations-bucket-terms-aggregation.html#search-aggregations-bucket-terms-aggregation-script

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值