elasticsearch之Terms Aggregation

本文详细解读了Elasticsearch中的桶聚合(TermsAggregation),如何通过术语聚合查找文档中特定字段的唯一值,并计算相关统计。实例展示了如何获取国家-省份-平均年龄的分组数据,以及关键参数如size、shard_size、min_doc_count等的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

Bucket aggregations本文译为桶聚合
桶聚合(bucket aggregation)不像指标聚合(Metric aggregation)那样计算字段的指标,而是创建文档存储桶。 每个存储桶都与一个标准(取决于聚合类型)相关联,该标准确定当前上下文中的文档是否“落入”其中。 换句话说,存储桶有效地定义了文档集。 除了存储桶本身之外,存储桶聚合还计算并返回落入每个存储桶的文档数量。

Terms Aggregation

术语聚合(Terms Aggregation)在文档的指定字段中搜索唯一值,并为找到的每个唯一值构建存储桶。
给出一个稍微复杂的例子:获取每个每个国家中每个省份的平均年龄

GET users/_search
{
  "size": 0,
  "aggs": {
    "countries": {
      "terms": {
        "field": "country"
      },
      "aggs": {
        "provinces": {
          "terms": {
            "field": "province"
          },
          "aggs": {
            "average_age": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
      }
    }
  }
}

响应结果:

  "aggregations" : {
    "countries" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "cn",
          "doc_count" : 3,
          "countries" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "zhejiang",
                "doc_count" : 2,
                "average_age" : {
                  "value" : 32.0
                }
              },
              {
                "key" : "shanghai",
                "doc_count" : 1,
                "average_age" : {
                  "value" : 30.0
                }
              }
            ]
          }
        },
        {
          "key" : "us",
          "doc_count" : 3,
          "countries" : {
            "doc_count_error_upper_bound" : 0,
            "sum_other_doc_count" : 0,
            "buckets" : [
              {
                "key" : "newyork",
                "doc_count" : 2,
                "average_age" : {
                  "value" : 33.0
                }
              },
              {
                "key" : "pennsylvania",
                "doc_count" : 1,
                "average_age" : {
                  "value" : 44.0
                }
              }
            ]
          }
        }
      ]
    }

从结果可以看到terms agg返回是各个buckets,每个bucket都有对应的key和属于该桶的文档数doc_count。默认情况下,响应将返回10个桶。当然也可以指定size参数改变返回的桶的数量。
下面说下对应的参数含义和用途

  • size:size 参数指定返回的桶的数量,默认值10。当size的值小于对应field真实个数时,返回的doc_count可能不是精确的。

官方给出了详细的例子,总结就是,因为每个shard节点都有返回最合适size个结果,然后基于每个shard节点的结果,给出最终合适的size结果给客户端,这就存在误差,比如某个term在其中一个节点的文档数小于top size的排序,则这个节点的term的文档数,不会返回作为最终结果的一部分,导致数据不准确。

  • shard_size:上面讲到size的大小可能影响数据的精确,当我们每次查询都把size设置超大的时候是可以保证数据的精确,但是代价也是很大的,因为每个shard节点都要获取size大小返回到客户端,最终得到最优的结果,(特殊是数据规模较大的数据)导致es内部网络开销比较大,而且shard节点返回的大部分数据都是无用的。所以就有了shard_size可以控制每个shard节点返回对应的size的大小。默认情况下,shard_size的大小为 (size * 1.5 + 10)
  • sum_other_doc_count:表示不在size分桶中文档个数。
  • doc_count_error_upper_bound:这个值表示的是在聚合中,没有在最终结果中的term最大可能有doc_count_error_upper_bound个文档。这是ES预估可能出现的最坏的结果,它的计算公式是每个shard节点最后一个term文档数之和(例如size是10,就是取每个shard排序第10个term文档数之和)
  • show_term_doc_count_error:显示每个分桶可能错误的上限。是个boolean值,默认是false,需改为true,才会显示。它的计算方式是:响应结果中的term,把没有返回该term的shard节点,最后一个term文档数加起来之和。(例如响应结果中有anhui,但是其中有一个shard节点,该anhuiterm并没有在前size中,那么该值就是第sizeterm文档数)。
  • order:聚合结果按照指定域排序。默认情况下,是按照doc_count降序排序的。返回对应size个分桶。
举几个例子
按照文档数升序
"order" : { "_count" : "asc" }
按照term字符串升序
"order" : { "_term" : "asc" }
还可以按照子聚合的参数进行排序,建议到官网查看。
也是可以多个条件一起,组合成排序集合
"order" : [{ "_term" : "asc" },{ "_count" : "asc" }]
  • min_doc_count:限制响应结果的最小文档数,如果桶中文档数小于指定的文档数,将不会响应给客户端,默认值1。
  • includeexclude:根据业务只展示有需要的term。
{
    "aggs" : {
        "tags" : {
            "terms" : {
                "field" : "tags",
                "include" : ".*sport.*",
                "exclude" : "water_.*"
            }
        }
    }
}

{
    "aggs" : {
        "JapaneseCars" : {
             "terms" : {
                 "field" : "make",
                 "include" : ["mazda", "honda"]
             }
         },
        "ActiveCarManufacturers" : {
             "terms" : {
                 "field" : "make",
                 "exclude" : ["rover", "jensen"]
             }
         }
    }
}
  • 分组:当响应返回大量的桶时,我们可以把这些桶进行分组,然后分组处理。
{
   "size": 0,
   "aggs": {
      "expired_sessions": {
         "terms": {
            "field": "account_id",
            "include": {
               "partition": 0,
               "num_partitions": 20
            },
            "size": 10000,
            "order": {
               "_term": "asc"
            }
         }
      }
   }
}

例如上面的分组,account_id存在大量的不同值,所以采用分组返回,分组字段为:num_partitions, 获取对应分组的数据为partition,范围为[0-num_partitions-1],每个分组的大小为:size

分组内的排序不是全局排序,只是当前分组内数据的排序。

  • collect mode:作用是延迟计算子聚合。
    当有子聚合时候,可以选择合适的子聚合模式,分为广度优先breadth_first和深度优先depth_first
    顾名思义,当父聚合项有很多唯一值,但是要求返回的size却很小,那么此时使用深度优先breadth_first比较合适。因为此时优先确定size个父项,然后在计算对应的自聚合,相对来说更加节省计算资源,但是因为要优先确定size个父项,所以父项聚合所有的数据都要放入到内存中,其实是更加吃内存的。
    depth_first模式会逐一计算对应的父聚合和子聚合,在计算下一个父聚合和子聚合,只保存size个父项集合即可。但是需要所有的父子聚合,所以对于上面的情况更加耗费性能。
{
    "aggs" : {
        "actors" : {
             "terms" : {
                 "field" : "actors",
                 "size" : 10,
                 "collect_mode" : "breadth_first" 
             },
            "aggs" : {
                "costars" : {
                     "terms" : {
                         "field" : "actors",
                         "size" : 5
                     }
                 }
            }
         }
    }
}
  • ** missing value**:当文档不存在对应的term,默认聚合将不会把这些文档计算在内,但是可以设置默认值,例如可以找不出不存在该值文档的个数等等。
{
    "aggs" : {
        "tags" : {
             "terms" : {
                 "field" : "tags",
                 "missing": "other_ value" 
             }
         }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值