腳本聚合框架有助於基於搜索查詢提供聚合數據。它基於稱爲聚合的簡單構建塊,可以進行組合以構建複雜的數據摘要。
聚合可以看作是在一組文檔上建立分析信息的工作單元。執行的上下文定義此文檔集是什麼(例如,在已執行的查詢/搜索請求的過濾器的上下文中執行頂級聚合)。
有許多不同類型的聚合,每種聚合都有自己的目的和輸出。爲了更好地理解這些類型,通常更容易將它們分爲四個主要家族:
桶裝:生成存儲桶的一組聚合,其中每個存儲桶都與一個鍵和一個文檔條件相關聯。執行聚合時,將對上下文中的每個文檔評估所有存儲桶條件,並且當條件匹配時,該文檔將被視爲“落入”相關存儲桶。到聚合過程結束時,我們將得到一個存儲桶列表-每個存儲桶都有一組“屬於”的文檔。
公制:聚集可跟蹤和計算一組文檔的指標。
矩陣:一類聚合,可在多個字段上進行操作,並根據從請求的文檔字段中提取的值生成矩陣結果。與指標和存儲桶聚合不同,此聚合系列尚不支持腳本。
管道:彙總其他彙總及其相關指標的輸出的彙總
接下來是有趣的部分。由於每個存儲桶有效地定義了一個文檔集(所有屬於該存儲桶的文檔),因此可以潛在地在存儲桶級別關聯聚合,並且這些聚合將在該存儲桶的上下文中執行。這就是聚合真正的力量所在:聚合可以嵌套!
構建聚合
以下代碼段捕獲了聚合的基本結構:
"aggregations" : {
"<aggregation_name>" : {
"<aggregation_type>" : {
<aggregation_body>
}
[,"meta" : { [<meta_data_body>] } ]?
[,"aggregations" : { [<sub_aggregation>]+ } ]?
}
[,"<aggregation_name_2>" : { ... } ]*
}
JSON中的aggregations
對象(aggs
也可以使用鍵)保存要計算的聚合。每個集合都與用戶定義的邏輯名稱相關聯(例如,如果集合計算平均價格,則將其命名爲avg_price
)。這些邏輯名稱還將用於唯一地標識響應中的聚合。每個聚合都有特定的類型(<aggregation_type>
在上面的代碼段中),通常是命名聚合主體中的第一個鍵。每種聚合類型都定義自己的主體,具體取決於聚合的性質(例如,avg
特定字段上的彙總將定義將在其上計算平均值的字段)。在聚合類型定義的同一級別上,可以選擇定義一組其他聚合,儘管僅當您定義的聚合具有存儲特性時纔有意義。在這種情況下,將爲存儲桶聚合構建的所有存儲桶計算您在存儲桶聚合級別上定義的子聚合。例如,如果您在聚合下定義一組range
聚合,則將爲定義的範圍存儲區計算子聚合。
價值觀來源
一些彙總處理從彙總文檔中提取的值。通常,將從使用field
聚合鍵設置的特定文檔字段中提取值。也可以定義一個 script
將生成值的文檔(每個文檔)。
爲聚合配置了field
和script
設置時,腳本將被視爲 value script
。在文檔級別評估普通腳本(即腳本可以訪問與文檔關聯的所有數據)時,價值腳本在價值級別評估。在這種模式下,從配置中提取值,field
並script
使用值對這些值進行“轉換”。
Elasticsearch在映射中使用字段的類型,以弄清楚如何運行聚合並設置響應格式。但是,在兩種情況下,Elasticsearch無法找出此信息:未映射的字段(例如,在多個索引之間的搜索請求中,只有其中一些具有該字段的映射)和純腳本。在這種情況下,可以使用value_type
選項爲Elasticsearch提供提示,該選項接受以下值:string
,long
(適用於所有整數類型), double
(適用於所有十進制類型,例如float
或scaled_float
)date
, ip
和boolean
。
一、指標彙總
1.平均聚合
single-value
度量聚集,計算的是從聚集的文檔中提取數值的平均數。這些值可以從文檔中的特定數字字段中提取,也可以由提供的腳本生成。
假設數據由代表學生考試成績(介於0到100之間)的文檔組成,我們可以使用以下方法取平均分數:
POST /exams/_search?size=0
{
"aggs" : {
"avg_grade" : { "avg" : { "field" : "grade" } }
}
}
以上彙總計算了所有文檔的平均成績。聚合類型爲avg
,該field
設置定義將在其上計算平均值的文檔的數字字段。上面將返回以下內容:
{
...
"aggregations": {
"avg_grade": {
"value": 75.0
}
}
}
聚合的名稱(avg_grade
)還可以用作鍵名,通過該鍵可以從返回的響應中檢索聚合結果。
Script
根據Script計算平均成績:
POST /exams/_search?size=0
{
"aggs" : {
"avg_grade" : {
"avg" : {
"script" : {
"source" : "doc.grade.value"
}
}
}
}
}
這會將script
參數解釋爲inline
具有painless
腳本語言且沒有腳本參數的腳本。要使用存儲的腳本,請使用以下語法:
POST /exams/_search?size=0
{
"aggs" : {
"avg_grade" : {
"avg" : {
"script" : {
"id": "my_script",
"params": {
"field": "grade"
}
}
}
}
}
}
Script的值
事實證明,該考試遠遠超出了學生的水平,因此需要進行成績更正。我們可以使用Script的值來獲取新的平均值:
POST /exams/_search?size=0
{
"aggs" : {
"avg_corrected_grade" : {
"avg" : {
"field" : "grade",
"script" : {
"lang": "painless",
"source": "_value * params.correction",
"params" : {
"correction" : 1.2
}
}
}
}
}
}
缺失值
該missing
參數定義應如何處理缺少值的文檔。默認情況下,它們將被忽略,但也可以將它們視爲具有值。
POST /exams/_search?size=0
{
"aggs" : {
"grade_avg" : {
"avg" : {
"field" : "grade",
"missing": 10
}
}
}
}
2.加權平均聚合
single-value
度量聚集,計算數字值的加權平均值被從聚合文檔中提取。這些值可以從文檔中的特定數字字段中提取。
在計算常規平均值時,每個數據點都具有相等的``權重''...它對最終值的貢獻均等。另一方面,加權平均對每個數據點的加權不同。每個數據點對最終值的貢獻量是從文檔中提取的,或由腳本提供的。
作爲公式,加權平均值爲 ∑(value * weight) / ∑(weight)
可以將規則平均值視爲每個值的隱式權重爲的加權平均值1
。
表3. weighted_avg
參數
參數名稱 | 描述 | 需要 | 默認值 |
---|---|---|---|
|
提供值的字段或腳本的配置 |
需要 |
|
|
提供權重的字段或腳本的配置 |
需要 |
|
|
數字響應格式化程序 |
可選的 |
|
|
有關純腳本或未映射字段的值的提示 |
可選的 |
|
在value
和weight
對象有每場具體配置:
表4. value
參數
參數名稱 | 描述 | 需要 | 默認值 |
---|---|---|---|
|
應當從中提取值的字段 |
需要 |
|
|
如果字段完全丟失,則使用的值 |
可選的 |
|
表5. weight
參數
參數名稱 | 描述 | 需要 | 默認值 |
---|---|---|---|
|
應從中提取權重的字段 |
需要 |
|
|
如果字段完全丟失,則使用的權重 |
可選的 |
|
範例
如果我們的文檔有一個"grade"
包含0-100數值分數的"weight"
字段和一個包含任意數值權重的字段,我們可以使用以下方法計算加權平均值:
POST /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade"
},
"weight": {
"field": "weight"
}
}
}
}
}
產生如下響應:
{
...
"aggregations": {
"weighted_grade": {
"value": 70.0
}
}
}
雖然每個字段允許多個值,但僅允許一個權重。如果聚合遇到的文檔具有多個權重(例如,weight字段是多值字段),它將引發異常。如果遇到這種情況,則需要script指定
爲權重字段 ,然後使用腳本將多個值組合成一個要使用的值。
該單個權重將獨立應用於從value
字段中提取的每個值。
此示例說明如何使用單個權重對具有多個值的單個文檔進行平均:
POST /exams/_doc?refresh
{
"grade": [1, 2, 3],
"weight": 2
}
POST /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade"
},
"weight": {
"field": "weight"
}
}
}
}
}
這三個值(1
,2
和3
)將作爲獨立值包括在內,其權重爲2
:
{
...
"aggregations": {
"weighted_grade": {
"value": 2.0
}
}
}
聚合返回2.0
結果,這與我們手工計算時所期望的相匹配: ((1*2) + (2*2) + (3*2)) / (2+2+2) == 2
腳本
值和權重都可以從腳本而不是字段中派生。作爲一個簡單的示例,以下內容將使用腳本在文檔的等級和權重中添加一個:
POST /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"script": "doc.grade.value + 1"
},
"weight": {
"script": "doc.weight.value + 1"
}
}
}
}
}
缺少值
該missing
參數定義應如何處理缺少值的文檔。默認行爲是不同的value
和weight
:
默認情況下,如果value
缺少該字段,則忽略該文檔,並將聚合移至下一個文檔。如果weight
缺少該字段,則假定其權重爲1
(類似於正常平均值)。
可以使用以下missing
參數覆蓋這兩個默認值:
POST /exams/_search
{
"size": 0,
"aggs" : {
"weighted_grade": {
"weighted_avg": {
"value": {
"field": "grade",
"missing": 2
},
"weight": {
"field": "weight",
"missing": 3
}
}
}
}
}
3.基數聚合
single-value
度量聚集,計算不同的值的近似計數。值可以從文檔中的特定字段中提取,也可以由腳本生成。
假設您正在爲商店的銷售建立索引,並希望計算與查詢匹配的已售產品的唯一數量:
POST /sales/_search?size=0
{
"aggs" : {
"type_count" : {
"cardinality" : {
"field" : "type"
}
}
}
}
產生的響應爲:
{
...
"aggregations" : {
"type_count" : {
"value" : 3
}
}
}
精確控制
此聚合還支持以下precision_threshold
選項:
POST /sales/_search?size=0
{
"aggs" : {
"type_count" : {
"cardinality" : {
"field" : "type",
"precision_threshold": 100
}
}
}
}