分桶聚合 #
Bucket aggregations 将文件集归类为桶。桶聚合的类型决定了一个给定的文档是否落入一个桶中
你可以使用桶聚合来实现分面导航(通常作为侧边栏放在搜索结果页面),以帮助你的用户缩小搜索结果范围。
terms #
terms
聚合为字段的每个唯一 term 动态地创建一个桶。
下面的例子使用 terms
聚合来查找网络日志数据中每个响应码的文档数量:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"response_codes": {
"terms": {
"field": "response.keyword",
"size": 10
}
}
}
}
Sample Response #
...
"aggregations" : {
"response_codes" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "200",
"doc_count" : 12832
},
{
"key" : "404",
"doc_count" : 801
},
{
"key" : "503",
"doc_count" : 441
}
]
}
}
...
值以 key
为键返回。
doc_count
指定每个桶中的文档数量。默认情况下,桶是按照 doc_count
的降序排序的。
响应还包括 2 个键 doc_count_error_upper_bound
和 sum_other_doc_count
。
term
聚合返回排名靠前的唯一 term 。因此,如果数据有许多唯一的 term,那么其中一些可能不会出现在结果中。 sum_other_doc_count
字段是被遗漏在响应外的文档的总和。在这种情况下,这个数字是 0,因为所有的唯一值都出现在响应中。
doc_count_error_upper_bound
字段表示最终结果中遗漏的唯一值的最大可能计数。使用此字段可以估计计数的误差范围。
计数可能不准确。负责聚合的协调节点会提示每个分片输入其最重要的唯一 term 。假设“size”参数为 3。
terms
聚合请求每个 shard 的前 3 个唯一 term 。协调节点获取每个结果并聚合它们以计算最终结果。如果一个 shard 包含的结果不属于前 3 个,则它不会显示在响应中。
如果 `size' 被设置为一个较低的数字,这一点尤其正确。因为默认的大小是 10 ,不太可能发生错误。如果你不需要很高的精度,想提高性能,你可以调低 size 。
sampler, diversified_sampler #
如果你要对数以百万计的文档进行聚合,你可以使用 sampler
聚合,将范围缩小到一小部分文档的样本,以获得更快的响应。 sampler
聚合通过得分最高的文档来选择样本。
其结果是近似的,但几乎代表真实数据的分布。 sampler
聚合明显提高了查询性能,但估计的响应并不完全可靠。
基础语法:
“aggs”: {
"SAMPLE": {
"sampler": {
"shard_size": 100
},
"aggs": {...}
}
}
The shard_size
属性告诉 Easysearch 从每个分片收集多少文档(最多)。
下面的例子将每个分片上收集的文档数量限制为 1,000 ,然后通过 terms
聚合对文档进行分类。
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"sample": {
"sampler": {
"shard_size": 1000
},
"aggs": {
"terms": {
"terms": {
"field": "agent.keyword"
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"sample" : {
"doc_count" : 1000,
"terms" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
"doc_count" : 368
},
{
"key" : "Mozilla/5.0 (X11; Linux i686) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24",
"doc_count" : 329
},
{
"key" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)",
"doc_count" : 303
}
]
}
}
}
...
diversified_sampler
聚合让你减少样本池分布的偏差。你可以使用 field
设置来控制在任何一个分片上收集到的共享一个共同值的文件的最大数量。
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"sample": {
"diversified_sampler": {
"shard_size": 1000,
"field": "response.keyword"
},
"aggs": {
"terms": {
"terms": {
"field": "agent.keyword"
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"sample" : {
"doc_count" : 3,
"terms" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
"doc_count" : 2
},
{
"key" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)",
"doc_count" : 1
}
]
}
}
}
...
significant_terms, significant_text #
significant_terms
聚合让你发现相对于索引中的其他数据,过滤后的子集中出现的不寻常或有趣的 term 。
前台集合是你所过滤的文档集。背景集合是一个索引中所有文档的集合。
significant_terms
聚合检查前台集合中的所有文档,并找到一个与后台集合中的文档相对应的重要出现的分数。
在样本网络日志数据中,每个文档都有一个包含访问者的客户端的字段。这个例子搜索了所有来自 iOS 操作系统的请求。对这个前台集合进行常规的 terms
聚合,会返回 Firefox,因为它在这个桶中拥有最多的文档。另一方面,significant_terms
聚合返回 Internet Explorer(IE),因为 IE 在前台集合中的出现次数明显高于后台集合。
GET kibana_sample_data_logs/_search
{
"size": 0,
"query": {
"terms": {
"machine.os.keyword": [
"ios"
]
}
},
"aggs": {
"significant_response_codes": {
"significant_terms": {
"field": "agent.keyword"
}
}
}
}
响应示例 #
...
"aggregations" : {
"significant_response_codes" : {
"doc_count" : 2737,
"bg_count" : 14074,
"buckets" : [
{
"key" : "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)",
"doc_count" : 818,
"score" : 0.01462731514608217,
"bg_count" : 4010
},
{
"key" : "Mozilla/5.0 (X11; Linux x86_64; rv:6.0a1) Gecko/20110421 Firefox/6.0a1",
"doc_count" : 1067,
"score" : 0.009062566630410223,
"bg_count" : 5362
}
]
}
}
...
如果 significant_terms
聚合没有返回任何结果,你可能没有用查询来过滤结果。另外,前景集的术语分布可能与背景集相同,这意味着前景集没有任何异常。
significant_text
聚合与 significant_terms
聚合类似,但它是针对原始文本字段。
Significant text 使用统计分析来衡量前景和背景集之间测得的受欢迎程度变化。例如,当您寻找其股票首字母缩略词 TSLA 时,它可能会建议 Tesla 。
significant_text
聚合动态重新分析源文本,过滤干扰数据,如重复段落、样板页眉和页脚等,否则可能会扭曲结果。
重新分析高基数数据集可能是一项 CPU 密集型操作。我们建议在采样器聚合中使用 significant_text
聚合,以将分析限制在一小部分最匹配的文档中,例如 200 个。
您可以设置以下参数:
min_doc_count
- 返回匹配超过配置的热门命中数的结果。 我们建议不要将min_doc_count
设置为 1,因为它往往会返回拼写错误或拼写错误的术语。 找到一个术语的多个实例有助于强化其重要性不是一次性事故的结果。 默认值 3 用于提供最小证据权重。shard_size
- 设置较高的值会以牺牲计算性能为代价提高稳定性(和准确性)。shard_min_doc_count
- 如果您的文本包含许多低频词并且您对这些不感兴趣(例如拼写错误),那么您可以设置shard_min_doc_count
参数以合理确定不会达到要求的分片级别过滤掉候选词min_doc_count
即使在合并本地重要文本频率之后。 默认值为 1,除非您明确设置它,否则它不会产生任何影响。 我们建议将此值设置为远低于min_doc_count
的值。
假设您在 Easysearch 集群中索引了莎士比亚的全集。您可以在 text_entry
字段中找到与 “breathe” 一词相关的重要文本:
GET shakespeare/_search
{
"query": {
"match": {
"text_entry": "breathe"
}
},
"aggregations": {
"my_sample": {
"sampler": {
"shard_size": 100
},
"aggregations": {
"keywords": {
"significant_text": {
"field": "text_entry",
"min_doc_count": 4
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"my_sample" : {
"doc_count" : 59,
"keywords" : {
"doc_count" : 59,
"bg_count" : 111396,
"buckets" : [
{
"key" : "breathe",
"doc_count" : 59,
"score" : 1887.0677966101694,
"bg_count" : 59
},
{
"key" : "air",
"doc_count" : 4,
"score" : 2.641295376716233,
"bg_count" : 189
},
{
"key" : "dead",
"doc_count" : 4,
"score" : 0.9665839666414213,
"bg_count" : 495
},
{
"key" : "life",
"doc_count" : 5,
"score" : 0.9090787433467572,
"bg_count" : 805
}
]
}
}
}
...
与 breathe
相关的最重要的文本是 air
, dead
, 和 life
。
significant_text
聚合有以下限制:
- 不支持子聚合,因为子聚合的内存成本很高。作为解决方法,您可以使用带有 include 子句和子聚合的
terms
聚合来添加后续查询。 - 不支持嵌套对象,因为它适用于文档 JSON 源。
- 文档计数可能有一些(通常很小)不准确,因为它基于对从每个分片返回的样本求和。您可以使用
shard_size
参数来微调准确性和性能之间的权衡。默认情况下,shard_size
设置为 -1 以自动估计分片数量和size
参数。
对于 significant_terms
和 significant_text
聚合,背景词频率的默认统计信息源是整个索引。您可以使用背景过滤器缩小此范围以获得更多焦点:
GET shakespeare/_search
{
"query": {
"match": {
"text_entry": "breathe"
}
},
"aggregations": {
"my_sample": {
"sampler": {
"shard_size": 100
},
"aggregations": {
"keywords": {
"significant_text": {
"field": "text_entry",
"background_filter": {
"term": {
"speaker": "JOHN OF GAUNT"
}
}
}
}
}
}
}
}
missing #
如果索引中的文档根本不包含聚合字段或聚合字段的值为 NULL,请使用 missing
参数指定应放置此类文档的存储桶的名称。
以下示例将任何缺失值添加到名为 “N/A” 的存储桶中:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"response_codes": {
"terms": {
"field": "response.keyword",
"size": 10,
"missing": "N/A"
}
}
}
}
因为 min_doc_count
参数的默认值为 1,所以 missing
参数不会在其响应中返回任何桶。将 min_doc_count
参数设置为 0 以查看响应中的 “N/A” 存储桶:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"response_codes": {
"terms": {
"field": "response.keyword",
"size": 10,
"missing": "N/A",
"min_doc_count": 0
}
}
}
}
响应示例 #
...
"aggregations" : {
"response_codes" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "200",
"doc_count" : 12832
},
{
"key" : "404",
"doc_count" : 801
},
{
"key" : "503",
"doc_count" : 441
},
{
"key" : "N/A",
"doc_count" : 0
}
]
}
}
...
histogram, date_histogram #
histogram
聚合桶文档基于指定的间隔。
使用 histogram
聚合,您可以非常轻松地可视化给定文档范围内值的分布。现在,Easysearch 当然不会返回实际图表,这就是 Kibana 的用途。但它会给你 JSON 响应,你可以用它来构建你自己的图。
以下示例按 10,000 间隔对 number_of_bytes
字段进行存储:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"number_of_bytes": {
"histogram": {
"field": "bytes",
"interval": 10000
}
}
}
}
响应示例 #
...
"aggregations" : {
"number_of_bytes" : {
"buckets" : [
{
"key" : 0.0,
"doc_count" : 13372
},
{
"key" : 10000.0,
"doc_count" : 702
}
]
}
}
...
The date_histogram
聚合使用日期数学为时间序列数据生成直方图。
例如,您可以找到您的网站每月获得的点击次数:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"logs_per_month": {
"date_histogram": {
"field": "@timestamp",
"interval": "month"
}
}
}
}
响应示例 #
...
"aggregations" : {
"logs_per_month" : {
"buckets" : [
{
"key_as_string" : "2020-10-01T00:00:00.000Z",
"key" : 1601510400000,
"doc_count" : 1635
},
{
"key_as_string" : "2020-11-01T00:00:00.000Z",
"key" : 1604188800000,
"doc_count" : 6844
},
{
"key_as_string" : "2020-12-01T00:00:00.000Z",
"key" : 1606780800000,
"doc_count" : 5595
}
]
}
}
...
T 响应包含三个月的日志。如果将这些值绘制成图表,您可以逐月查看网站请求流量的峰值和谷值。
range, date_range, ip_range #
The range
聚合允许您定义每个桶的范围。
例如,您可以找到 1000 和 2000、2000 和 3000、3000 和 4000 之间的字节数。
在 range
参数中,您可以将范围定义为数组里的对象。
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"number_of_bytes_distribution": {
"range": {
"field": "bytes",
"ranges": [
{
"from": 1000,
"to": 2000
},
{
"from": 2000,
"to": 3000
},
{
"from": 3000,
"to": 4000
}
]
}
}
}
}
响应包括 from
键值并排除 to
键值:
Sample response #
...
"aggregations" : {
"number_of_bytes_distribution" : {
"buckets" : [
{
"key" : "1000.0-2000.0",
"from" : 1000.0,
"to" : 2000.0,
"doc_count" : 805
},
{
"key" : "2000.0-3000.0",
"from" : 2000.0,
"to" : 3000.0,
"doc_count" : 1369
},
{
"key" : "3000.0-4000.0",
"from" : 3000.0,
"to" : 4000.0,
"doc_count" : 1422
}
]
}
}
...
date_range
聚合在概念上与 range
聚合相同,只是它允许您执行日期数学运算
例如,您可以获取最近 10 天的所有文档。为了使日期更具可读性,请在格式中包含一个 format
参数:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"number_of_bytes": {
"date_range": {
"field": "@timestamp",
"format": "MM-yyyy",
"ranges": [
{
"from": "now-10d/d",
"to": "now"
}
]
}
}
}
}
响应示例 #
...
"aggregations" : {
"number_of_bytes" : {
"buckets" : [
{
"key" : "03-2021-03-2021",
"from" : 1.6145568E12,
"from_as_string" : "03-2021",
"to" : 1.615451329043E12,
"to_as_string" : "03-2021",
"doc_count" : 0
}
]
}
}
...
ip_range
聚合用于 IP 地址。
它适用于 ip
类型字段。您可以在
CIDR 表示法中定义 IP 范围和掩码。
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"access": {
"ip_range": {
"field": "ip",
"ranges": [
{
"from": "1.0.0.0",
"to": "126.158.155.183"
},
{
"mask": "1.0.0.0/8"
}
]
}
}
}
}
响应示例 #
...
"aggregations" : {
"access" : {
"buckets" : [
{
"key" : "1.0.0.0/8",
"from" : "1.0.0.0",
"to" : "2.0.0.0",
"doc_count" : 98
},
{
"key" : "1.0.0.0-126.158.155.183",
"from" : "1.0.0.0",
"to" : "126.158.155.183",
"doc_count" : 7184
}
]
}
}
...
filter, filters #
filter
聚合是一个查询子句,与搜索查询(match
或 term
或 range
)完全一样。在创建存储桶之前,您可以使用 filter
聚合将整个文档集缩小到特定的集合。
以下示例显示了在过滤器上下文中运行的 avg
聚合。 avg
聚合仅聚合与 range
查询匹配的文档:
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"low_value": {
"filter": {
"range": {
"taxful_total_price": {
"lte": 50
}
}
},
"aggs": {
"avg_amount": {
"avg": {
"field": "taxful_total_price"
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"low_value" : {
"doc_count" : 1633,
"avg_amount" : {
"value" : 38.363175998928355
}
}
}
}
filters
聚合与 filter
聚合相同,只是它允许您使用多个过滤器聚合。
filter
聚合产生单个桶,而 filters
聚合返回多个桶,每个桶对应一个定义的过滤器。
要为所有与任何过滤器查询都不匹配的文档创建一个存储桶,请将 other_bucket
属性设置为 true
:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"200_os": {
"filters": {
"other_bucket": true,
"filters": [
{
"term": {
"response.keyword": "200"
}
},
{
"term": {
"machine.os.keyword": "osx"
}
}
]
},
"aggs": {
"avg_amount": {
"avg": {
"field": "bytes"
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"200_os" : {
"buckets" : [
{
"doc_count" : 12832,
"avg_amount" : {
"value" : 5897.852711970075
}
},
{
"doc_count" : 2825,
"avg_amount" : {
"value" : 5620.347256637168
}
},
{
"doc_count" : 1017,
"avg_amount" : {
"value" : 3247.0963618485744
}
}
]
}
}
...
global #
global
聚合让您可以脱离过滤器聚合的聚合上下文。即使您包含了一个筛选查询来缩小一组文档的范围, global
聚合也会对所有文档进行聚合,就好像筛选查询不存在一样。它忽略 filter
聚合并隐式假设 match_all
查询。
以下示例返回索引中所有文档的 taxful_total_price
字段的 avg
值:
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"query": {
"range": {
"taxful_total_price": {
"lte": 50
}
}
},
"aggs": {
"total_avg_amount": {
"global": {},
"aggs": {
"avg_price": {
"avg": {
"field": "taxful_total_price"
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"total_avg_amount" : {
"doc_count" : 4675,
"avg_price" : {
"value" : 75.05542864304813
}
}
}
...
您可以看到,当查询匹配时,taxful_total_price
字段的平均值为 75.05 而不是 filter
示例中看到的 38.36。
geo_distance, geohash_grid #
geo_distance
聚合根据与原始 geo_point
字段的距离将文档分组为同心圆。
它与 range
聚合相同,只是它适用于地理位置。
例如,您可以使用 geo_distance
聚合来查找距离您 1 公里以内的所有披萨店。搜索结果仅限于您指定的 1 公里半径范围内,但您可以添加在 2 公里范围内找到的其他结果。
您只能在映射为 geo_point 的字段上使用 geo_distance 聚合
一个点是一个单一的地理坐标,例如您的智能手机显示的当前位置。 Easysearch 中的一个点表示如下:
{
"location": {
"type": "point",
"coordinates": {
"lat": 83.76,
"lon": -81.2
}
}
}
您还可以将纬度和经度指定为数组 [-81.20, 83.76]
或字符串 "83.76, -81.20"
此表列出了 geo_distance
聚合的相关字段:
字段 | 描述 | 是否必需 |
---|---|---|
field | 指定您要处理的地理点字段。 | Yes |
origin | 指定用于计算距离的地理点。 | Yes |
ranges | 根据文档与目标点的距离,指定一个范围列表来收集文档。 | Yes |
unit | 定义“范围”数组中使用的单位。 unit 默认为 m (米),但您可以切换为其他单位,例如 km (千米)、mi (英里)、in (英寸)、yd (码)、 cm (厘米)和 mm (毫米)。 | No |
distance_type | 指定 Easysearch 如何计算距离。默认值为 sloppy_arc (更快但不太准确),但也可以设置为 arc (较慢但最准确)或 plane (最快但最不准确)。由于误差幅度大,请仅对小地理区域使用 plane 。 | No |
语法如下:
{
"aggs": {
"aggregation_name": {
"geo_distance": {
"field": "field_1",
"origin": "x, y",
"ranges": [
{
"to": "value_1"
},
{
"from": "value_2",
"to": "value_3"
},
{
"from": "value_4"
}
]
}
}
}
}
此示例根据距 geo-point
字段的以下距离形成桶:
- 少于 10 公里
- 从 10 到 20 公里
- 从 20 到 50 公里
- 从 50 到 100 公里
- 100 公里以上
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"position": {
"geo_distance": {
"field": "geo.coordinates",
"origin": {
"lat": 83.76,
"lon": -81.2
},
"ranges": [
{
"to": 10
},
{
"from": 10,
"to": 20
},
{
"from": 20,
"to": 50
},
{
"from": 50,
"to": 100
},
{
"from": 100
}
]
}
}
}
}
响应示例 #
...
"aggregations" : {
"position" : {
"buckets" : [
{
"key" : "*-10.0",
"from" : 0.0,
"to" : 10.0,
"doc_count" : 0
},
{
"key" : "10.0-20.0",
"from" : 10.0,
"to" : 20.0,
"doc_count" : 0
},
{
"key" : "20.0-50.0",
"from" : 20.0,
"to" : 50.0,
"doc_count" : 0
},
{
"key" : "50.0-100.0",
"from" : 50.0,
"to" : 100.0,
"doc_count" : 0
},
{
"key" : "100.0-*",
"from" : 100.0,
"doc_count" : 14074
}
]
}
}
...
用于地理分析的 geohash_grid
聚合存储桶文档。它将一个地理区域组织成一个由不同大小或精度的较小区域组成的网格。较低的精度值表示较大的地理区域,较高的值表示较小、更精确的地理区域。
查询返回的结果数量可能太多,无法在地图上单独显示每个地理点。 geohash_grid
聚合通过计算每个点的 Geohash,以您定义的精度级别(在 1 到 12 之间;默认值为 5)将附近的地理点聚集在一起。要了解有关 Geohash 的更多信息,请参阅
维基百科。
Web 日志示例数据分布在较大的地理区域,因此您可以使用较低的精度值。您可以通过增加精度值来放大此地图:
GET kibana_sample_data_logs/_search
{
"size": 0,
"aggs": {
"geo_hash": {
"geohash_grid": {
"field": "geo.coordinates",
"precision": 4
}
}
}
}
响应示例 #
...
"aggregations" : {
"geo_hash" : {
"buckets" : [
{
"key" : "c1cg",
"doc_count" : 104
},
{
"key" : "dr5r",
"doc_count" : 26
},
{
"key" : "9q5b",
"doc_count" : 20
},
{
"key" : "c20g",
"doc_count" : 19
},
{
"key" : "dr70",
"doc_count" : 18
}
...
]
}
}
...
您可以使用 Kibana 在地图上可视化聚合响应。
您希望聚合越准确,Easysearch 消耗的资源就越多,因为聚合必须计算的桶数。默认情况下,Easysearch 不会生成超过 10,000 个桶。您可以使用 size
属性更改此行为,但请记住,对于包含数千个存储桶的非常宽的查询,性能可能会受到影响。
adjacency_matrix #
adjacency_matrix
聚合允许您定义过滤器表达式并返回相交过滤器的矩阵,其中矩阵中的每个非空单元格代表一个桶。您可以找到有多少文档属于任何过滤器组合。
使用 adjacency_matrix
聚合通过将数据可视化为图形来发现概念之间的关系。
例如,在示例电子商务数据集中,分析不同制造公司之间的关系:
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"interactions": {
"adjacency_matrix": {
"filters": {
"grpA": {
"match": {
"manufacturer.keyword": "Low Tide Media"
}
},
"grpB": {
"match": {
"manufacturer.keyword": "Elitelligence"
}
},
"grpC": {
"match": {
"manufacturer.keyword": "Oceanavigations"
}
}
}
}
}
}
}
响应示例 #
{
...
"aggregations" : {
"interactions" : {
"buckets" : [
{
"key" : "grpA",
"doc_count" : 1553
},
{
"key" : "grpA&grpB",
"doc_count" : 590
},
{
"key" : "grpA&grpC",
"doc_count" : 329
},
{
"key" : "grpB",
"doc_count" : 1370
},
{
"key" : "grpB&grpC",
"doc_count" : 299
},
{
"key" : "grpC",
"doc_count" : 1218
}
]
}
}
}
让我们仔细看看结果:
{
"key": "grpA&grpB",
"doc_count": 590
}
grpA
: 由 Low Tide Media 制造的产品。grpB
: Elitelligence 制造的产品。590
: 双方生产的产品数量。
您可以使用 Kibana 通过网络图来表示此数据。
nested, reverse_nested #
nested
聚合允许您聚合嵌套对象内的字段。 nested
类型是对象数据类型的特殊版本,它允许对象数组以一种可以彼此独立查询的方式进行索引
使用 object
类型,所有数据都存储在同一个文档中,因此搜索匹配可以跨越子文档。例如,假设一个带有 pages
的 logs
索引被映射为 object
数据类型:
PUT logs/_doc/0
{
"response": "200",
"pages": [
{
"page": "landing",
"load_time": 200
},
{
"page": "blog",
"load_time": 500
}
]
}
Easysearch 合并实体关系的所有子属性,看起来像这样:
{
"logs": {
"pages": ["landing", "blog"],
"load_time": ["200", "500"]
}
}
因此,如果您想使用 pages=landing
和 load_time=500
搜索此索引,即使着陆的 load_time
值为 200,此文档也符合条件。
如果您想确保不会发生此类跨对象匹配,请将字段映射为“嵌套”类型:
PUT logs
{
"mappings": {
"properties": {
"pages": {
"type": "nested",
"properties": {
"page": { "type": "text" },
"load_time": { "type": "double" }
}
}
}
}
}
嵌套文档允许您索引相同的 JSON 文档,但会将您的页面保存在单独的 Lucene 文档中,从而只进行诸如 pages=landing
和 load_time=200
之类的搜索返回预期结果。在内部,嵌套对象将数组中的每个对象作为单独的隐藏文档进行索引,这意味着每个嵌套对象都可以独立于其他对象进行查询。
您必须指定相对于包含嵌套文档的父级的嵌套路径:
GET logs/_search
{
"query": {
"match": { "response": "200" }
},
"aggs": {
"pages": {
"nested": {
"path": "pages"
},
"aggs": {
"min_load_time": { "min": { "field": "pages.load_time" } }
}
}
}
}
响应示例 #
...
"aggregations" : {
"pages" : {
"doc_count" : 2,
"min_price" : {
"value" : 200.0
}
}
}
...
您还可以将嵌套文档中的值聚合到它们的父文档中;此聚合称为 reverse_nested
。
在按嵌套对象中的字段分组后,您可以使用 reverse_nested
聚合父文档中的字段。 reverse_nested
聚合返回根页面并获取每个变量的 load_time
。
reverse_nested
聚合是嵌套聚合内的子聚合。它接受一个名为 path
的选项。此选项定义 Easysearch 在文档层次结构中向后计算聚合所需的步数。
GET logs/_search
{
"query": {
"match": { "response": "200" }
},
"aggs": {
"pages": {
"nested": {
"path": "pages"
},
"aggs": {
"top_pages_per_load_time": {
"terms": {
"field": "pages.load_time"
},
"aggs": {
"comment_to_logs": {
"reverse_nested": {},
"aggs": {
"min_load_time": {
"min": {
"field": "pages.load_time"
}
}
}
}
}
}
}
}
}
}
响应示例 #
...
"aggregations" : {
"pages" : {
"doc_count" : 2,
"top_pages_per_load_time" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : 200.0,
"doc_count" : 1,
"comment_to_logs" : {
"doc_count" : 1,
"min_load_time" : {
"value" : null
}
}
},
{
"key" : 500.0,
"doc_count" : 1,
"comment_to_logs" : {
"doc_count" : 1,
"min_load_time" : {
"value" : null
}
}
}
]
}
}
}
...
响应显示日志索引有一页的 load_time
为 200,另一页的 load_time
为 500。