• Elasticsearch聚合语句


    聚合的范围是search query过滤出的数据

    四种聚合类型:

    一、Bucketing

    桶聚合,常规的分类然后计算每个分类的文档数量

    二、Metric

    分类并对一组文档进行sum、avg等数学运算

    三、Matrix

    可在多个字段上计算,生成矩阵结果

    四、Pipeline

    对聚合的结果再次聚合

    Pipeline aggregations 会在所有的聚类执行完毕之后才执行

    聚合语句的结构

    "aggs" : {
        "<aggregation_name>" : {
            "<aggregation_type>" : {
                <aggregation_body>
            }
            [,"meta" : {  [<meta_data_body>] } ]?
            [,"aggregations" : { [<sub_aggregation>]+ } ]?
        }
        [,"<aggregation_name_2>" : { ... } ]*
    }
    

    Terms Aggregation

    会根据字段的值动态构建buckets

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

    返回:

    {
        ...
        "aggregations" : {
            "genres" : {
                "doc_count_error_upper_bound": 0, 
                "sum_other_doc_count": 0, 
                "buckets" : [ 
                    {
                        "key" : "jazz",
                        "doc_count" : 10
                    },
                    {
                        "key" : "rock",
                        "doc_count" : 10
                    },
                    {
                        "key" : "electronic",
                        "doc_count" : 10
                    },
                ]
            }
        }
    }
    

    当字段的值很多的时候,elasticsearch只会返回部分buckets,sum_other_doc_count表示没有被返回的 buckets 中 document 的数量之和

    size

    默认情况下,elasticsearch只会返回按照doc_count降序排序的前10个terms,可以配置size参数来修改这一默认行为

    terms聚合的结果是不精确的

    https://mp.weixin.qq.com/s/V4cGqvkQ7-DgeSvPSketgQ

    比如设置size = 3,表示希望返回TOP3的结果

    每个索引分片会取自己分片上TOP3返回协调节点,协调节点汇总后再取汇总结果的TOP3

    因此,这个结果是跟全量取TOP3不一样的,所以说terms聚合的结果是不精确的

    size 和 shard_size 有什么区别?

    • size:是聚合结果的返回值,客户期望返回聚合排名前三,size值就是 3。
    • shard_size: 每个分片上聚合的数据条数。shard_size 原则上要大于等于 size(若设置小于size,实则没有意义,elasticsearch 会默认置为size)

    请求的size值越高,结果将越准确,但计算最终结果的成本也将越高。

    推荐设置 shard_size 为比较大的值,官方推荐:size*1.5+10

    Order

    buckets的排序可以由order参数定义

    按doc数量升序排序:

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

    按terms的字符升序排序:

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

    按子聚类的结果排序:

    {
        "aggs" : {
            "genres" : {
                "terms" : {
                    "field" : "genre",
                    "order" : { "max_play_count" : "desc" }
                },
                "aggs" : {
                    "max_play_count" : { "max" : { "field" : "play_count" } }
                }
            }
        }
    }
    

    min_doc_count

    默认值为1,表示只返回doc_count大于等于1的buckets

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

    Nested Aggregation

    针对nested字段的聚合,比如

    {
        ...
    
        "product" : {
            "properties" : {
                "resellers" : { 
                    "type" : "nested",
                    "properties" : {
                        "name" : { "type" : "text" },
                        "price" : { "type" : "double" }
                    }
                }
            }
        }
    }
    

    求价格最低的产品的聚合语句可以写成:

    {
        "query" : {
            "match" : { "name" : "led tv" }
        },
        "aggs" : {
            "resellers" : {
                "nested" : {
                    "path" : "resellers"
                },
                "aggs" : {
                    "min_price" : { "min" : { "field" : "resellers.price" } }
                }
            }
        }
    }
    

    需要在顶层聚类的path字段填入nested的字段名称,然后,在子聚类中再针对子字段聚类

    Date Histogram Aggregation 日期直方图

    比如,想要统计每天的商品销量

    GET /goods/_search
    {
      "query": {
          "bool": {
            "filter": [
              {
                "range": {
                  "date_list": {
                  "gte": "2020-8-1",
                  "lt": "2020-8-2"
                  }
                }
              }
            ]
          }
      },
      "size": 0,
      "aggs": {
        "date_count": {
          "date_histogram": {
            "field": "date_list",
            "format": "yyyy-MM-dd",
            "interval": "day"
          }
        }
      }
    }
    

    根据过滤的结果数据,以天为间隔聚类绘制直方图

    {
      "took": 82,
      "timed_out": false,
      "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
      },
      "hits": {
        "total": 34841,
        "max_score": 0,
        "hits": []
      },
      "aggregations": {
        "date_count": {
          "buckets": [
            {
              "key_as_string": "2020-06-02",
              "key": 1591056000000,
              "doc_count": 17
            },
            {
              "key_as_string": "2020-06-03",
              "key": 1591142400000,
              "doc_count": 387
            },
    ...
    

    会出现6月的聚类结果是因为date_list是一组数据,可能某个document的这个字段即包含8月2日又包含6月2日,那么它将即被放到8-2的桶也被放到6-2的桶

    时间间隔

    时间间隔单位的可选项:year, quarter, month, week, day, hour, minute, second

    精确指定时间间隔:1.5h也可以写成90m

    时间格式

    在es内部,日期被表示为一个64位的时间戳(milliseconds-since-the-epoch),这正是bucket key字段的值。key_as_string字段的格式可以由format参数决定

    如果不指定format,则es会选此字段mapping的第一个日期格式

    offset

    当使用day作为时间间隔的时候,每个桶的范围是0点至0点,设置offset+6h表示将桶的范围改为6am to 6am

    GET my_index/_search?size=0
    {
      "aggs": {
        "by_day": {
          "date_histogram": {
            "field":     "date",
            "interval":  "day",
            "offset":    "+6h"
          }
        }
      }
    }
    

    Keyed Response

    keyed标签置为true表示bucket将以hashmap格式返回,key_as_string作为key

    POST /sales/_search?size=0
    {
        "aggs" : {
            "sales_over_time" : {
                "date_histogram" : {
                    "field" : "date",
                    "interval" : "1M",
                    "format" : "yyyy-MM-dd",
                    "keyed": true
                }
            }
        }
    }
    

    Response:

    {
        ...
        "aggregations": {
            "sales_over_time": {
                "buckets": {
                    "2015-01-01": {
                        "key_as_string": "2015-01-01",
                        "key": 1420070400000,
                        "doc_count": 3
                    },
                    "2015-02-01": {
                        "key_as_string": "2015-02-01",
                        "key": 1422748800000,
                        "doc_count": 2
                    },
                    "2015-03-01": {
                        "key_as_string": "2015-03-01",
                        "key": 1425168000000,
                        "doc_count": 2
                    }
                }
            }
        }
    }
    

    Missing value

    如果不定义missingdate字段缺失的文档将被忽略。这样定义后,这些文档会被归入2000/01/01

    POST /sales/_search?size=0
    {
        "aggs" : {
            "sale_date" : {
                 "date_histogram" : {
                     "field" : "date",
                     "interval": "year",
                     "missing": "2000/01/01" 
                 }
             }
        }
    }
    

    根据聚合的结果进行过滤

    https://elasticsearch.cn/article/13501

    每个IP登录次数超过5次的IP

    {
      "aggs": {
        "IP": {
          "terms": {
            "field": "IP",
            "size": 3000,
            "order": {
              "_count": "desc"
            },
            "min_doc_count": 5
          }
        }
      },
      "size": 0
    }
    

    会筛选出大于或等于5的buckets

    每个IP登录人数超过2的IP

    {
      "aggs": {
        "IP": {
          "terms": {
            "field": "IP",
            "size": 3000,
            "order": {
              "distinct": "desc"
            },
            "min_doc_count": 5
          },
          "aggs": {
            "distinct": {
              "cardinality": {
                "field": "IP.keyword"
              }
            },
            "dd":{
              "bucket_selector": {
                "buckets_path": {"userCount":"distinct"},
                "script": "params.userCount > 2"
              }
            }
          }
        }
      },
      "size": 0
    }
    

    bucket_selector必须出现在子聚合中,并且只能针对子聚合的数字结果过滤,script必须返回一个bool

    Post Filter

    post filter允许用户在执行聚合函数之后再对hits做过滤,比如:

    GET /shirts/_search
    {
      "query": {
        "bool": {
          "filter": {
            "term": { "brand": "gucci" } 
          }
        }
      },
      "aggs": {
        "colors": {
          "terms": { "field": "color" } 
        },
        "color_red": {
          "filter": {
            "term": { "color": "red" } 
          },
          "aggs": {
            "models": {
              "terms": { "field": "model" } 
            }
          }
        }
      },
      "post_filter": { 
        "term": { "color": "red" }
      }
    }
    

    由于aggs的范围取决于query,因此不能在一开始就过滤出颜色为红色的

  • 相关阅读:
    Netty检查连接断开的几种方法
    docker部署RabbitMQ集群
    docker部署elk日志采集系统(kafka方式)
    docker部署elk日志采集系统(tcp方式)
    Chrome浏览器RCE 0Day漏洞PoC公开--漏洞复现
    LLMNR和NetBIOS欺骗--获取win7 ntlm-hash
    利用php配置文件构成后门
    zabbix 用sendEmail发邮件
    Exchange 2013 ecp中启用重置用户密码功能
    CentOS7下使用yum安装MariaDB
  • 原文地址:https://www.cnblogs.com/luozx207/p/13517727.html
Copyright © 2020-2023  润新知