欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 20:54:21
...

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

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

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

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

- final result
1 Product A (100)
2 Product Z (52)
3 Product C (50)
4 Product G (45)
5 Product 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

相关标签: big data