Elasticsearch 聚合

1、前言

聚合是一種基於搜索的數據彙總,經過組合能夠完成複雜的操做。聚合能夠對文檔進行彙總、分組等。經過聚合,咱們會獲得一個數據的概覽,是分析和總結所有的數據,而不是尋找單個文檔。html

2、分類

  • Bucket Aggregation:一些列知足特定條件的文檔的集合,相似MySQL的「group by」
  • Metric Aggregation:一些數學運算,能夠對文檔字段進行統計分析,好比max、min、sum等。
  • Pipeline Aggregation:對其餘的聚合結果進行二次聚合
  • Matrix Aggregation:支持對多個字段的操做並提供一個結果矩陣,7.x版本合併到Metric Aggregation中了。

3、聚合結構

{
    "size": 0, 
    ["query": {}, ]?
    "aggs" : {
        "${my_name}" : {
            "${aggregation_type}" : {
                <aggregation_body>
            }
            [,"meta" : {  [<meta_data_body>] } ]?
            [,"aggs" : { [<sub_aggregation>]+ } ]?
        }
        [,"${my_name}" : { ... } ]*
    }
}
  • 聚合能夠進行嵌套,好比上面的「aggs」內部又嵌套了一個「aggs」
  • 「aggs」是簡寫,也能夠寫完整「aggregations」
  • 最上面的「size」通常設置爲0,聚合操做用於統計數據,無需輸出文檔
  • query 查詢,可選
  • my_name 自定義名字

4、測試數據

使用kibana導入「kibana_sample_data_flights」,這個是飛機的航班信息,有地區、價格、天氣等信息。git

操做路徑:Home --> 添加數據 --> 樣例數據 --> Sample flight dataelasticsearch

5、Bucket Aggregation

一、子聚合

根據目的地(DestCountry)進行分組,查看航班的數量分佈式

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "dest_count": {
      "terms": {
        "field": "DestCountry"
      }
    }
  }
}

二、數字區間分組

根據價格區間進行分組,好比0到100元多少個,100到200元多少個ide

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "price_stat": {     // 自定義名字
      "histogram": {
        "field": "AvgTicketPrice",
        "interval": 100     // 指定區間
      }
    }
  }
}

輸出的結果中,key爲「100.0」表明0到100.0的數據,計算公式以下性能

bucket_key = Math.floor(value / interval) * interval

三、日期區間分組

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "price_stat": {
      "date_histogram": {
        "field": "timestamp",
        "calendar_interval": "month"
      }
    }
  }
}

注意:日期間隔設置,7.x版本用「calendar_interval」,老版本用「interval」。測試

支持的時間間隔表達式優化

  • 分鐘:minute, 1m
  • 小時:hour, 1h
  • 天:day, 1d
  • 星期:week, 1w
  • 月:month, 1M
  • 季度:quarter, 1q
  • 年:year, 1y

6、Metric Aggregation

計算度量這類的聚合操做是以使用一種方式或者從文檔中提取須要聚合的值爲基礎的。這些數據不但能夠從文檔(使用數據屬性)的屬性中提取出來,也可使用腳本生成。ui

支持max、min、count、sum、avg、stats(各類統計信息)、cardinality(去重後數量)、percentiles(百分位)、geo_bounds(地理邊界)code

一、最值

輸出航班的最大價格,最小价格

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "max_price": {
      "max": {
        "field": "AvgTicketPrice"
      }
    },
    "mix_price": {
      "min": {
        "field": "AvgTicketPrice"
      }
    }
  }
}

二、嵌套操做

輸出各個目的地航班的最大價格,最小价格

GET kibana_sample_data_flights/_search
{
  "size": 0, 
  "aggs": {
    "dest_count":{
      "terms": {
        "field": "DestCountry"
      },
      "aggs": {
        "max_price": {
          "max": {
            "field": "AvgTicketPrice"
          }
        },
        "min_price": {
          "min": {
            "field": "AvgTicketPrice"
          }
        }
      }
    }
  }
}

三、stats

一次性輸出各類統計結果,包括count、min、max、sum、avg

GET kibana_sample_data_flights/_search
{
  "size": 0, 
  "aggs": {
    "my_stats":{
      "stats": {
        "field": "AvgTicketPrice"
      }
    }
  }
}

四、cardinality

去重後數量統計

GET kibana_sample_data_flights/_search
{
  "size": 0, 
  "aggs": {
    "my_cardinality":{
      "cardinality": {
        "field": "DestCountry"
      }
    }
  }
}

五、top_hits

top_hits 操做,最開頭的幾個文檔。
獲取去每一個國家的航班的最小价格,下面的「"size": 5」表明獲取5個國家的航班,「"size": 2」表明最低的2個價格。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "my_count": {
      "terms": {
        "field": "DestCountry",
        "size": 5
      },
      "aggs": {
        "my_min_price": {
          "top_hits": {
            "size": 2,
            "sort": [
              {
                "AvgTicketPrice": {
                  "order": "asc"
                }
              }
            ]
          }
        }
      }
    }
  }
}

六、ranges 自定義範圍分組

好比下面,小於200一個分組,200到500一個分組,大於500個分組,能夠指定輸出的key。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "my_price_range":{
      "range": {
        "field": "AvgTicketPrice",
        "ranges": [
          {
            "to": 200
          },
          {
            "from": 200,
            "to": 500
          },
          {
            "key": ">500", 
            "from": 500
          }
        ]
      }
    }
  }
}

七、百分位聚合

百分位聚合,能夠利用百分位聚合的結果評估數據分佈,判斷數據是否扭曲,判斷數據是否雙峯分佈等。壓測的時候常用,好比95百分位對應的值表示這個值大於95%的全部值。假設結果是「10%:12ms ,..., 70%:55ms, 99%:100ms」,說明一般狀況下(70%),網頁的響應時間在12ms~55ms,99%的網頁在100ms內加載完成。

GET kibana_sample_data_flights/_search
{
  "size": 0, 
  "aggs": {
    "my_price_percentiles":{
      "percentiles": {
        "field": "AvgTicketPrice",
        "percents": [
          1,
          5,
          25,
          50,
          75,
          95,
          99
        ]
      }
    }
  }
}

八、地理邊界聚合

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "my_geo_bounds": {
      "geo_bounds": {
        "field": "DestLocation",
        "wrap_longitude": true
      }
    }
  }
}

九、優化 Terms 聚合的性能

設置 eager_global_ordinals 爲true,會在內存中預先加載這些數據。

7、Pipeline Aggregation

對聚合分析的結果再次作聚合分析。

分兩類

  • Sibling:結果和現有分析結果同級。有min_bucket、max_bucket、avg_bucket、sum_bucket、stats_bucket、percentiles_bucket
  • Parent:結果內嵌到現有的聚合分析結果之中。有derivative(差值,與前一個的差值,用於看趨勢)、cumulative_sum(累計求和)、moving_avg(移動平均,數據在一個固定大小窗口裏的平均值)

說明,bucket_path參數,指定路徑,若是是二級路徑,注意有一個「>」。

一、Sibling的例子

根據不一樣的目的地獲取平均票據,並對這些平均票價作分析。
注意,my_distancemy_avg_pricemy_result這三個是自定義的變量名,buckets_path指定路徑。

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "my_distance": {
      "terms": {
        "field": "DestCountry"
      },
      "aggs": {
        "my_avg_price": {
          "avg": {
            "field": "AvgTicketPrice"
          }
        }
      }
    },
    "my_result": {
      "stats_bucket": {
        "buckets_path": "my_distance>my_avg_price"
      }
    }
  }
}

二、Parent的例子

統計每50km的平均票價,並查看其波動

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "my_distance": {
      "histogram": {
        "field": "DistanceKilometers",
        "interval": 50
      },
      "aggs": {
        "my_avg_price": {
          "avg": {
            "field": "AvgTicketPrice"
          }
        },
        "my_result": {
          "derivative": {
            "buckets_path": "my_avg_price"
          }
        }
      }
    }
  }
}

8、排序

根據數量(_count)進行排序,數量相同根據返回的key進行排序

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "dest_count": {
      "terms": {
        "field": "DestCountry",
        "order": [
          {
            "_count": "asc"
          },
          {
            "_key": "desc"
          }
        ]
      }
    }
  }
}

根據最終返回的結果進行排序,好比下面的my_stats

GET kibana_sample_data_flights/_search
{
  "size": 0,
  "aggs": {
    "my_distance": {
      "terms": {
        "field": "DestCountry",
        "order": {
          "my_stats.min": "asc"
        }
      },
      "aggs": {
        "my_stats": {
          "stats": {
            "field": "AvgTicketPrice"
          }
        }
      }
    }
  }
}

9、聚合分析的原理及精準度問題

聚合分析

Terms 聚合分析不許的緣由,數據分散在多個分片上,Coordinating Node 沒法獲取數據全貌。

打開 show_term_doc_count_error,能夠多看到兩個返回值。

  • doc_count_error_upper_bound:被遺漏的term 分桶,包含的文檔,有可能的最大值
  • sum_other_doc_count:除了返回結果 bucket的 terms 之外,其餘 terms 的文檔總數(總數-返回的總數)

Trems 不正確的案例

那麼如何解決呢?

  • 解決方案 1:當數據量不大時,設置 Primary Shard 爲 1;實現準確性。
  • 解決方案 2:在分佈式數據上,設置 shard_size 參數,提升精確度。原理:每次從 Shard 上額外多獲取數據,提高準確率,但會下降響應時間。

shard_size 的默認大小 「shard_size = size * 1.5 * 10」,能夠根據本身的須要進行設置。

10、資料

相關文章
相關標籤/搜索