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,因此不能在一開始就過濾出顏色為紅色的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM