天天看點

Elasticsearch聚合初步了解(後續會繼續更新)聚合

聚合

聚合傳回基于query 查詢的結果進行聚合計算後的資料。有以下四大類:

支援腳本。一些列構造桶的聚合,每個桶都與一個key和一個文檔分類标準相關聯。當聚合執行時,所有的文檔分類标準(依據)對每個文檔進行判斷,将其分類到其滿足的桶中。此類聚合執行的結果是:我們得到了桶的集合,每個桶内都含有滿足該桶分類依據的文檔。

桶聚合可以有子聚合(桶聚合或者名額聚合)

  • 名額
支援腳本。能夠跟蹤聚合軌迹且在一系列文檔上計算名額的聚合類型。
  • 矩陣
不支援腳本。可以在從請求文檔内提取的多個字段值上操作并生成矩陣結果。
  • 管道
對其他聚合的結果和與其關聯的名額進行聚合處理。

聚合可以嵌套,可以在桶聚合中嵌套名額聚合,這是聚合的真正威力所在。

聚合操作用于對double類型資料進行處理。是以,如果聚合操作用于絕對值大于2^53 的long型資料,聚合結果可能是近似值。

聚合的結構
"aggregations" : {
    "<aggregation_name>" : {
        "<aggregation_type>" : {
            <aggregation_body>
        }
        [,"meta" : {  [<meta_data_body>] } ]?
        [,"aggregations" : { [<sub_aggregation>]+ } ]?
    }
    [,"<aggregation_name_2>" : { ... } ]*
}
           
子聚合隻能夠在桶聚合中使用。
Values Source
  • 腳本
  • 對沒有mapping的字段,使用value_type.

名額聚合

名額聚合根據從文檔某個字段中提取出的值或者使用腳本對文檔字段中的值進行處理後的值計算出名額。
數字名額聚合是名額聚合中比較特殊的類型,它隻傳回數字。有些聚合傳回單個數字值(如avg)而有些聚合傳回多個數字值(如stats).這些名額聚合在作為桶排序的直接子聚合時扮演重要角色(某些聚合要求将桶排序聚合的結果按照幾個字段值的統計值排序傳回)。

平均數聚合

計算文檔某字段值平均值,這些字段值可以是文檔字段值,也可以是腳本生成的值。
curl -X POST "localhost:9200/exams/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "aggs" : {
        "avg_grade" : {
            "avg" : {
                "script" : {
                    "source" : "doc.grade.value"
                }
            }
        }
    }
}
'
curl -X POST "localhost:9200/exams/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "aggs" : {
        "avg_grade" : {
            "avg" : {
                "script" : {
                    "id": "my_script",
                    "params": {
                        "field": "grade"
                    }
                }
            }
        }
    }
}
'
curl -X POST "localhost:9200/exams/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "aggs" : {
        "avg_corrected_grade" : {
            "avg" : {
                "field" : "grade",
                "script" : {
                    "lang": "painless",
                    "source": "_value * params.correction",
                    "params" : {
                        "correction" : 1.2
                    }
                }
            }
        }
    }
}
'

           
對 missing value 的文檔處理:預設情況下此文檔将會被忽略,我們可以為聚合字段缺失值的文檔指定一個固定的字段值。
curl -X POST "localhost:9200/exams/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "aggs" : {
        "grade_avg" : {
            "avg" : {
                "field" : "grade",
                "missing": 10 
            }
        }
    }
}
'
           

Cardinality Aggregation

一個擷取某個字段内唯一值的近似數目的單值名額聚合。用于統計的值既可以來自于某個字段也可以來自于腳本生成。
curl -X POST "localhost:9200/sales/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "aggs" : {
        "type_count" : {
            "cardinality" : {
                "field" : "_doc",
                "precision_threshold": 100 
            }
        }
    }
}
'
           
precision_threshold參數用于近似精度控制,此參數指定一個值,在此值之外,計數會有近似。此參數支援的最大值為:40000,設定大于40000的值的效果與設定40000的效果一樣,預設值是3000。此選項是以記憶體換精度,即精度提高,則意味着聚合消耗記憶體增加。

關于計數近似

如果要計算精确值,就需要将所有值加載到HashSet中,然後擷取集合size即可。但是這種方式在對大量資料或者大值字段進行處理時在記憶體消耗和分片之間的資訊交換上耗費巨大資源。
Cardinality 聚合基于 HyperLogLog++算法,此算法具有以下屬性:
  • 可配置的精度,以此來決定怎樣用記憶體換精度
  • 在低基數資料集聚合是精度非常高
  • 無論資料量多大,記憶體占用量僅由精度決定;如果我們設定精度是c,則記憶體使用量為 c * 8 位元組。
注:對大資料量的string字段來說,提前将字段的hash值存在文檔中,然後使用此hash值進行Cardinality 聚合無疑是最快的。可以使用Mapper Murmur3 Plugin來完成生成hash并存入文檔的工作。

Extended Stats Aggregation

對Stats Aggregation 的擴充,增加了:
  • sum_of_squares 平方和
  • variance 方差
  • std_deviation 标準差
  • std_deviation_bounds 标準差範圍(上下界)
标準差範圍,可以使用參數 sigma
curl -X GET "localhost:9200/exams/_search" -H 'Content-Type: application/json' -d'
{
    "size": 0,
    "aggs" : {
        "grades_stats" : {
            "extended_stats" : {
                "field" : "grade",
                "sigma" : 3 
            }
        }
    }
}
'
           

Geo Bounds Aggregation

傳回一個包含所有地理坐标點的邊界矩形。

Geo Centroid Aggregation

根據地理坐标資料擷取所有地理坐标點的中心位置點。

Max Aggregation

擷取最大值

Min Aggregation

擷取最小值

Percentiles Aggregation

根據數值字段生成一個或者多個百分位數值。預設情況下,百分位數聚合會生成[1,5,25,50,75,95,99]百分位的數值。我們也可以自定義傳回的百分位數位置。
curl -X GET "localhost:9200/latency/_search" -H 'Content-Type: application/json' -d'
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time",
                "percents" : [95, 99, 99.9] 
            }
        }
    }
}
'
           

Keyed Response

在預設情況下,keyed被設定為true,每個桶都與一個唯一的key值關聯且傳回的結果是一個hash而不是數組。可以将keyed設定為false來使傳回結果稱為數組。
# default keyed true
{
    ...

   "aggregations": {
      "load_time_outlier": {
         "values" : {
            "1.0": 5.0,
            "5.0": 25.0,
            "25.0": 165.0,
            "50.0": 445.0,
            "75.0": 725.0,
            "95.0": 945.0,
            "99.0": 985.0
         }
      }
   }
}
# keyed false
{
    ...

    "aggregations": {
        "load_time_outlier": {
            "values": [
                {
                    "key": 1.0,
                    "value": 5.0
                },
                {
                    "key": 5.0,
                    "value": 25.0
                },
                {
                    "key": 25.0,
                    "value": 165.0
                },
                {
                    "key": 50.0,
                    "value": 445.0
                },
                {
                    "key": 75.0,
                    "value": 725.0
                },
                {
                    "key": 95.0,
                    "value": 945.0
                },
                {
                    "key": 99.0,
                    "value": 985.0
                }
            ]
        }
    }
}
           

百分位數通常都是近似值

Elasticsearch在計算百分位數時使用TDigest算法:
  • 精确度與q*(1-q)成比例,這意味着極端百分位數比非極端百分位數更精确
  • 對少量資料,百分位數非常精确
  • 在桶内資料量變化時,百分位數計算結果會是近似值。

Compression

近似算法需要平衡記憶體使用率和預估精度。Elasticsearch使用參數Compression來做平衡:
curl -X GET "localhost:9200/latency/_search" -H 'Content-Type: application/json' -d'
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time",
                "tdigest": {
                  "compression" : 200 
                }
            }
        }
    }
}
'
           
TDigest 使用‘nodes’的數量來計算近似百分位數;nodes 的個數越多,與資料量相關的精确則越高,相應地占用的記憶體也就越高。compression參數限制nodes 數目的最大值為 20 * compression.
是以,設定更大的compression參數可以提高精确度,但是同時也增大了記憶體占用和算法執行耗時。compression預設值是100.
一個nodes 大概使用32 位元組記憶體。是以預設情況下,可能會占用64KB記憶體。實踐證明,資料分布越随機,TDigest占用記憶體越小。

HDR Histogram

高動态範圍直方圖。

Percentile Ranks Aggregation

百分位等級聚合,用于對數字值計算一個或者多個百分位等級。即它計算某個值在所有觀察值中的百分比排名,比如如果一個值大于或者等于95%的觀察值,則我們說這個值在第95的百分位等級上。
curl -X GET "localhost:9200/latency/_search" -H 'Content-Type: application/json' -d'
{
    "size": 0,
    "aggs" : {
        "load_time_ranks" : {
            "percentile_ranks" : {
                "field" : "load_time", 
                "values" : [500, 600]
            }
        }
    }
}
'
# 55%的資料小于或者等于500;64%的資料小于或者等于600
{
    ...

   "aggregations": {
      "load_time_ranks": {
         "values" : {
            "500.0": 55.00000000000001,
            "600.0": 64.0
         }
      }
   }
}
           

Scripted Metric Aggregation

該功能是實驗性質的,有可能在未來改變或者删除。
# 從銷售計算利潤
curl -X POST "localhost:9200/ledger/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "query" : {
        "match_all" : {}
    },
    "aggs": {
        "profit": {
            "scripted_metric": {
                "init_script" : "params._agg.transactions = []",
                "map_script" : "params._agg.transactions.add(doc.type.value == 'sale' ? doc.amount.value : -1 * doc.amount.value)", 
                "combine_script" : "double profit = 0; for (t in params._agg.transactions) { profit += t } return profit",
                "reduce_script" : "double profit = 0; for (a in params._aggs) { profit += a } return profit"
            }
        }
    }
}
'
curl -X POST "localhost:9200/ledger/_search?size=0" -H 'Content-Type: application/json' -d'
{
    "aggs": {
        "profit": {
            "scripted_metric": {
                "init_script" : {
                    "id": "my_init_script"
                },
                "map_script" : {
                    "id": "my_map_script"
                },
                "combine_script" : {
                    "id": "my_combine_script"
                },
                "params": {
                    "field": "amount", 
                    "_agg": {}        
                },
                "reduce_script" : {
                    "id": "my_reduce_script"
                }
            }
        }
    }
}
'
           

Stats Aggregation

傳回多個名額的聚合,傳回名額包括:
  • min
  • max
  • sum
  • count
  • avg

Sum Aggregation

傳回求和。

Top Hits Aggregation

作為子聚合,傳回每個桶内與查詢最相關的幾個文檔。
選項:
  • from
  • size 預設值 3
  • sort 桶内文檔排序方式。預設通過_score排序。
每個hit支援以下功能:
  • 高亮
  • Explain
  • Named filters and queries
  • Source filtering
  • stored fileds
  • scripted fields
  • Doc value fields
  • include versions
terms 聚合中不能使用 top_hits 作為排序選項值。
curl -X POST "localhost:9200/sales/_search" -H 'Content-Type: application/json' -d'
{
  "query": {
    "match": {
      "body": "elections"
    }
  },
  "aggs": {
    "top_sites": {
      "terms": {
        "field": "domain",
        "order": {
          "top_hit": "desc"
        }
      },
      "aggs": {
        "top_tags_hits": {
          "top_hits": {}
        },
        "top_hit" : {
          "max": {
            "script": {
              "source": "_score"
            }
          }
        }
      }
    }
  }
}
'
           

繼續閱讀