准備數據
創建索引
為了說明介紹中提到的各種存儲桶聚合,我們首先創建一個新的 “sports” 索引,該索引存儲 “althlete” 文檔的集合。 索引映射將包含諸如運動員的位置,姓名,等級,運動,年齡,進球數和場位置(例如防守者)之類的字段。 讓我們創建映射:
PUT sports
{
"mappings": {
"properties": {
"birthdate": {
"type": "date",
"format": "dateOptionalTime"
},
"location": {
"type": "geo_point"
},
"name": {
"type": "keyword"
},
"rating": {
"type": "integer"
},
"sport": {
"type": "keyword"
},
"age": {
"type": "integer"
},
"goals": {
"type": "integer"
},
"role": {
"type": "keyword"
},
"score_weight": {
"type": "float"
}
}
}
}
一旦 mapping 創建成功,我們就可以使用 Elasticsearch 所提供的 Bulk API 來把我們數據導入到我們的索引中。我們可以通過一個REST 調用就把所有的數據導入到 Elasticsearch 中。
POST sports/_bulk
{"index":{"_index":"sports"}}
{"name":"Michael","birthdate":"1989-10-1","sport":"Football","rating":["5","4"],"location":"46.22,-68.45","age":"23","goals":"43","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Bob","birthdate":"1989-11-2","sport":"Football","rating":["3","4"],"location":"45.21,-68.35","age":"33","goals":"54","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Jim","birthdate":"1988-10-3","sport":"Football","rating":["3","2"],"location":"45.16,-63.58","age":"28","goals":"73","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Joe","birthdate":"1992-5-20","sport":"Basketball","rating":["4","3"],"location":"45.22,-68.53","age":"18","goals":"848","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Tim","birthdate":"1992-2-28","sport":"Basketball","rating":["3","3"],"location":"46.22,-68.85","age":"28","goals":"942","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Alfred","birthdate":"1990-9-9","sport":"Football","rating":["2","2"],"location":"45.12,-68.35","age":"25","goals":"53","score_weight":"4","role":"defender"}
{"index":{"_index":"sports"}}
{"name":"Jeff","birthdate":"1990-4-1","sport":"Hockey","rating":["2","3"],"location":"46.12,-68.55","age":"26","goals":"93","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Will","birthdate":"1988-3-1","sport":"Hockey","rating":["4","4"],"location":"46.25,-84.25","age":"27","goals":"124","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Mick","birthdate":"1989-10-1","sport":"Football","rating":["3","4"],"location":"46.22,-68.45","age":"35","goals":"56","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Pong","birthdate":"1989-11-2","sport":"Basketball","rating":["1","3"],"location":"45.21,-68.35","age":"34","goals":"1483","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Ray","birthdate":"1988-10-3","sport":"Football","rating":["2","2"],"location":"45.16,-63.58","age":"31","goals":"84","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Ping","birthdate":"1992-5-20","sport":"Basketball","rating":["4","3"],"location":"45.22,-68.53","age":"27","goals":"1328","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Duke","birthdate":"1992-2-28","sport":"Hockey","rating":["5","2"],"location":"46.22,-68.85","age":"41","goals":"218","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Hal","birthdate":"1990-9-9","sport":"Hockey","rating":["4","2"],"location":"45.12,-68.35","age":"18","goals":"148","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Charge","birthdate":"1990-4-1","sport":"Football","rating":["3","2"],"location":"44.19,-82.55","age":"19","goals":"34","score_weight":"4","role":"defender"}
{"index":{"_index":"sports"}}
{"name":"Barry","birthdate":"1988-3-1","sport":"Football","rating":["5","2"],"location":"36.45,-79.15","age":"20","goals":"48","score_weight":"4","role":"defender"}
{"index":{"_index":"sports"}}
{"name":"Bank","birthdate":"1988-3-1","sport":"Handball","rating":["6","4"],"location":"46.25,-54.53","age":"25","goals":"150","score_weight":"4","role":"defender"}
{"index":{"_index":"sports"}}
{"name":"Bingo","birthdate":"1988-3-1","sport":"Handball","rating":["10","7"],"location":"46.25,-68.55","age":"29","goals":"143","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"James","birthdate":"1988-3-1","sport":"Basketball","rating":["10","8"],"location":"41.25,-69.55","age":"36","goals":"1284","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Wayne","birthdate":"1988-3-1","sport":"Hockey","rating":["10","10"],"location":"46.21,-68.55","age":"25","goals":"113","score_weight":"3","role":"midfielder"}
{"index":{"_index":"sports"}}
{"name":"Brady","birthdate":"1988-3-1","sport":"Handball","rating":["10","10"],"location":"63.24,-84.55","age":"29","goals":"443","score_weight":"2","role":"forward"}
{"index":{"_index":"sports"}}
{"name":"Lewis","birthdate":"1988-3-1","sport":"Football","rating":["10","10"],"location":"56.25,-74.55","age":"24","goals":"49","score_weight":"3","role":"midfielder"}
這樣我們的數據就錄入到 Elasticsearch 中了。在下面,我們就用不同的存儲桶來對我們的數據進行統計。
Filter(s) Aggregations
桶聚合支持單過濾器聚合和多過濾器聚合。
單個過濾器聚合根據與過濾器定義中指定的查詢或字段值匹配的所有文檔構造單個存儲桶。 當您要標識一組符合特定條件的文檔時,單過濾器聚合很有用。
例如,我們可以使用單過濾器聚合來查找所有具有 “defender” 角色的運動員,並計算每個過濾桶的平均目標。 過濾器配置如下所示:
POST sports/_search
{
"size": 0,
"aggs": {
"defender_filter": {
"filter": {
"term": {
"role": "defender"
}
},
"aggs": {
"avg_goals": {
"avg": {
"field": "goals"
}
}
}
}
}
}
我們看到的結果是:
"aggregations" : {
"defender_filter" : {
"doc_count" : 4,
"avg_goals" : {
"value" : 71.25
}
}
}
如你所見,filter 聚合包含一個 “term” 字段,該字段指定文檔中的字段以搜索特定值(在本例中為 “defender”)。 Elasticsearch 將遍歷所有文檔,並檢查 “role” 字段中是否包含 “defender”。 然后將與該值匹配的文檔添加到聚合生成的單個存儲桶中。此輸出表明我們集合中所有后衛的平均進球數為71.25。
這是單過濾器聚合的示例。 但是,在 Elasticsearch 中,你可以選擇使用 filter 聚合指定多個過濾器。 這是一個多值聚合,其中每個存儲桶都對應一個特定的過濾器。 我們可以修改上面的示例以過濾 defender 和 foward:
GET sports/_search
{
"size": 0,
"aggs": {
"athletes": {
"filters": {
"filters": {
"defenders": {
"term": {
"role": "defender"
}
},
"forwards": {
"term": {
"role": "forward"
}
}
}
},
"aggs": {
"avg_goals": {
"avg": {
"field": "goals"
}
}
}
}
}
}
顯示結果為:
"aggregations" : {
"athletes" : {
"buckets" : {
"defenders" : {
"doc_count" : 4,
"avg_goals" : {
"value" : 71.25
}
},
"forwards" : {
"doc_count" : 9,
"avg_goals" : {
"value" : 661.0
}
}
}
}
}
我們可以看出來我們同時有兩個桶,分別對應我們的兩個 filter。每一個 filter 都檢查 role 的值為 defender 或者 forward。
我們甚至可以在 Kibana 中展示這兩個桶的數據。為了能夠在 Kibana 中使用我們的數據,我們必須創建一個 index pattern。如果你還不了解這個,請參閱我之前的文章 “Kibana: 如何使用Search Bar”。在我們導入數據的時候,我們選擇 birthdate 字段作為時間系列的 timestamp。
如您所見,“goals” 字段上的平均子聚合是在Y軸上定義的。 在X軸上,我們創建兩個過濾器,並為它們指定 “defender” 和 “forward” 值。 由於平均指標是過濾器聚合的子聚合,因此 Elasticsearch 將創建的過濾器應用於 “goals” 字段,因此我們無需明確指定該字段。
Terms Aggregation
也許我們對 Terms aggregation 並不陌生。我們剛才在一開始已經使用了 terms aggregation。
術語聚合會在文檔的指定字段中搜索唯一值,並為找到的每個唯一值構建存儲桶。 與過濾器聚合不同,術語聚合的任務不是將結果限制為特定值,而是查找文檔中給定字段的所有唯一值。
看一下下面的示例,我們試圖為 “sport” 字段中找到的每個唯一值創建一個存儲桶。 這項操作的結果是,我們將為索引中的每種運動提供四個獨特的存儲桶:Football,Handball,Hockey 和 Basketbalk。 然后,我們將使用平均子聚合計算每種運動的平均目標:
GET sports/_search
{
"size": 0,
"aggs": {
"sports": {
"terms": {
"field": "sport"
},
"aggs": {
"avg_scoring": {
"avg": {
"field": "goals"
}
}
}
}
}
}
返回數據為:
"aggregations" : {
"sports" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Football",
"doc_count" : 9,
"avg_scoring" : {
"value" : 54.888888888888886
}
},
{
"key" : "Basketball",
"doc_count" : 5,
"avg_scoring" : {
"value" : 1177.0
}
},
{
"key" : "Hockey",
"doc_count" : 5,
"avg_scoring" : {
"value" : 139.2
}
},
{
"key" : "Handball",
"doc_count" : 3,
"avg_scoring" : {
"value" : 245.33333333333334
}
}
]
}
}
如你所見,術語聚合為索引中的每種運動類型構造了四個存儲桶。 每個存儲桶包含 doc_count(屬於存儲桶的文檔數)和每個運動的平均子聚合。
讓我們在 Kibana 中可視化這些結果:
如您所見,在Y軸上,我們在 “goals” 字段上使用平均子聚合,在X軸上,我們在 “sport” 字段上定義了術語桶聚合。
Histogram Aggregation
直方圖聚合使我們可以根據指定的時間間隔構造存儲桶。 屬於每個間隔的值將形成一個間隔存儲桶。 例如,假設我們要使用5年間隔將直方圖聚合應用於 “age” 字段。 在這種情況下,直方圖聚合將在我們的文檔集中找到最小和最大年齡,並將每個文檔與指定的時間間隔相關聯。 每個文檔的 “age” 字段將向下舍入到最接近的時間間隔存儲桶。 例如,假設我們的時間間隔值為5,存儲分區大小為6,則年齡32會四舍五入為30。
直方圖聚合的公式如下所示:
bucket_key = Math.floor((value - offset) / interval) * interval + offset
請注意,時間間隔必須為正十進制數,而偏移量必須為 [0,offset] 范圍內的十進制。
讓我們使用直方圖聚合來生成籃球中目標間隔為200的存儲桶。
POST sports/_search
{
"size": 0,
"aggs": {
"baskketball_filter": {
"filter": {
"term": {
"sport": "Basketball"
}
},
"aggs": {
"goals_histogram": {
"histogram": {
"field": "goals",
"interval": 200
}
}
}
}
}
}
返回結果:
"aggregations" : {
"baskketball_filter" : {
"doc_count" : 5,
"goals_histogram" : {
"buckets" : [
{
"key" : 800.0,
"doc_count" : 2
},
{
"key" : 1000.0,
"doc_count" : 0
},
{
"key" : 1200.0,
"doc_count" : 2
},
{
"key" : 1400.0,
"doc_count" : 1
}
]
}
}
}
上面的回答表明,沒有目標落在0-200、200-400、400-600和600-800區間內。 因此,第一個存儲區從800-1000間隔開始。 因此,值最小的文檔將確定最小存儲桶(最小key的存儲桶)。 相應地,具有最高值的文檔將確定最大存儲桶(具有最高key的存儲桶)。
此外,該響應還顯示有零個文檔落在[1000,1200)范圍內。 這意味着沒有運動員得分在1000到1200個目標之間。 默認情況下,Elasticsearch用空存儲桶填充此類空白。 您可以使用min_doc_count設置通過請求最小計數不為零的存儲桶來更改此行為。 例如,如果我們將 min_doc_count 的值設置為1,則直方圖將僅針對其中包含不少於1個文檔的間隔構造存儲桶。 讓我們修改查詢,將min_doc_count設置為1。
POST sports/_search
{
"size": 0,
"aggs": {
"baskketball_filter": {
"filter": {
"term": {
"sport": "Basketball"
}
},
"aggs": {
"goals_histogram": {
"histogram": {
"field": "goals",
"interval": 200,
"min_doc_count": 1
}
}
}
}
}
}
那么經過這樣修改后的返回結果是:
"aggregations" : {
"baskketball_filter" : {
"doc_count" : 5,
"goals_histogram" : {
"buckets" : [
{
"key" : 800.0,
"doc_count" : 2
},
{
"key" : 1200.0,
"doc_count" : 2
},
{
"key" : 1400.0,
"doc_count" : 1
}
]
}
}
}
我們還可以使用 extended_bounds 設置來強制直方圖聚合,以根據特定的最小值開始構建其存儲桶,並繼續構建存儲桶直至達到最大值(即使不再有文檔)。 僅當將 min_doc_count 設置為0時,才使用 extended_bounds。(如果min_doc_count大於0,則不會返回空存儲桶)。 看一下這個查詢:
POST sports/_search
{
"size": 0,
"aggs": {
"baskketball_filter": {
"filter": {
"term": {
"sport": "Basketball"
}
},
"aggs": {
"goals_histogram": {
"histogram": {
"field": "goals",
"interval": 200,
"min_doc_count": 0,
"extended_bounds": {
"min": 0,
"max": 1600
}
}
}
}
}
}
}
在這里,我們為存儲桶指定了0(最小值)和1600(最大值)。 因此,響應應如下所示:
"aggregations" : {
"baskketball_filter" : {
"doc_count" : 5,
"goals_histogram" : {
"buckets" : [
{
"key" : 0.0,
"doc_count" : 0
},
{
"key" : 200.0,
"doc_count" : 0
},
{
"key" : 400.0,
"doc_count" : 0
},
{
"key" : 600.0,
"doc_count" : 0
},
{
"key" : 800.0,
"doc_count" : 2
},
{
"key" : 1000.0,
"doc_count" : 0
},
{
"key" : 1200.0,
"doc_count" : 2
},
{
"key" : 1400.0,
"doc_count" : 1
},
{
"key" : 1600.0,
"doc_count" : 0
}
]
}
}
}
如您所見,即使第一個存儲桶和最后一個存儲桶根本沒有任何值,也會生成從0到結束1600的所有存儲桶。
Date histogram aggregation
這個聚合類似於正常的直方圖,但只能與日期或日期范圍值一起使用。 由於日期在 Elasticsearch 中內部以長值表示,因此也可以但不准確地對日期使用正常的直方圖。 這兩個 AP I的主要區別在於,可以使用日期/時間表達式指定間隔。 基於時間的數據需要特殊的支持,因為基於時間的間隔並不總是固定的長度。
在我們的數據中有一個叫做 birthdate 的字段。在建立我們的 index pattern 時,我們可以選擇這個字段作為 time series 的timest amp。下面是我們的數據的時序圖。
我們可以使用 date histogram aggregation 來統計我們的運動員出生年月分別情況:
GET sports/_search
{
"size": 0,
"aggs": {
"birthdays": {
"date_histogram": {
"field": "birthdate",
"interval": "year"
}
}
}
}
返回的結果是:
"aggregations" : {
"birthdays" : {
"buckets" : [
{
"key_as_string" : "1988-01-01T00:00:00.000Z",
"key" : 567993600000,
"doc_count" : 10
},
{
"key_as_string" : "1989-01-01T00:00:00.000Z",
"key" : 599616000000,
"doc_count" : 4
},
{
"key_as_string" : "1990-01-01T00:00:00.000Z",
"key" : 631152000000,
"doc_count" : 4
},
{
"key_as_string" : "1991-01-01T00:00:00.000Z",
"key" : 662688000000,
"doc_count" : 0
},
{
"key_as_string" : "1992-01-01T00:00:00.000Z",
"key" : 694224000000,
"doc_count" : 4
}
]
}
}
上面的結果顯示在1988年到1998年之間的運動員有10個,在1989和1990年之間的有4位。我們也可以在Kibana中表示出來。
當然我們也可以針對每個年齡段的 goals 的平均值:
GET sports/_search
{
"size": 0,
"aggs": {
"birthdays": {
"date_histogram": {
"field": "birthdate",
"interval": "year"
},
"aggs": {
"average_goals": {
"avg": {
"field": "goals"
}
}
}
}
}
}
返回的結果是:
"aggregations" : {
"birthdays" : {
"buckets" : [
{
"key_as_string" : "1988-01-01T00:00:00.000Z",
"key" : 567993600000,
"doc_count" : 10,
"average_goals" : {
"value" : 251.1
}
},
{
"key_as_string" : "1989-01-01T00:00:00.000Z",
"key" : 599616000000,
"doc_count" : 4,
"average_goals" : {
"value" : 409.0
}
},
{
"key_as_string" : "1990-01-01T00:00:00.000Z",
"key" : 631152000000,
"doc_count" : 4,
"average_goals" : {
"value" : 82.0
}
},
{
"key_as_string" : "1991-01-01T00:00:00.000Z",
"key" : 662688000000,
"doc_count" : 0,
"average_goals" : {
"value" : null
}
},
{
"key_as_string" : "1992-01-01T00:00:00.000Z",
"key" : 694224000000,
"doc_count" : 4,
"average_goals" : {
"value" : 834.0
}
}
]
}
}
我們可以看到在1992年的這個年齡段的 average_goals 是最高的,達到834。也許是后生可畏啊!我們也可以在 Kibana 中表示出來:
Range Aggregation
通過此存儲桶聚合,可以輕松根據用戶定義的范圍構建存儲桶。 Elasticsearch 將檢查從你指定的數字字段中提取的每個值,並將其與范圍進行比較,然后將該值放入相應的范圍。 請注意,此聚合包括起始值,但不包括每個范圍的起始值。
讓我們為運動索引中的 “age” 字段創建一個范圍匯總:
GET sports/_search
{
"size": 0,
"aggs": {
"goal_ranges": {
"range": {
"field": "age",
"ranges": [
{
"to": 20
},
{
"from": 20,
"to": 30
},
{
"from": 30
}
]
}
}
}
}
如您所見,我們為查詢指定了三個范圍。 這意味着Elasticsearch將創建與每個范圍相對應的三個存儲桶。 上面的查詢應產生以下輸出:
"aggregations" : {
"goal_ranges" : {
"buckets" : [
{
"key" : "*-20.0",
"to" : 20.0,
"doc_count" : 3
},
{
"key" : "20.0-30.0",
"from" : 20.0,
"to" : 30.0,
"doc_count" : 13
},
{
"key" : "30.0-*",
"from" : 30.0,
"doc_count" : 6
}
]
}
}
如輸出所示,我們指數中最多的運動員年齡在20至30歲之間。
為了使范圍更易理解,我們可以為每個范圍自定義鍵名,如下所示:
GET sports/_search
{
"size": 0,
"aggs": {
"goal_ranges": {
"range": {
"field": "age",
"ranges": [
{
"key": "start-of-career",
"to": 20
},
{
"key": "mid-of-career",
"from": 20,
"to": 30
},
{
"key": "end-of-cereer",
"from": 30
}
]
}
}
}
}
這樣產生的結果是:
"aggregations" : {
"goal_ranges" : {
"buckets" : [
{
"key" : "start-of-career",
"to" : 20.0,
"doc_count" : 3
},
{
"key" : "mid-of-career",
"from" : 20.0,
"to" : 30.0,
"doc_count" : 13
},
{
"key" : "end-of-cereer",
"from" : 30.0,
"doc_count" : 6
}
]
}
}
我們可以使用統計子聚合將更多信息添加到范圍。 此匯總將為每個范圍提供最小值,最大值,平均值和總和。 讓我們來看看:
GET sports/_search
{
"size": 0,
"aggs": {
"goal_ranges": {
"range": {
"field": "age",
"ranges": [
{
"key": "start-of-career",
"to": 20
},
{
"key": "mid-of-career",
"from": 20,
"to": 30
},
{
"key": "end-of-cereer",
"from": 30
}
]
},
"aggs": {
"age_stats": {
"stats": {
"field": "age"
}
}
}
}
}
}
查詢結果是:
"aggregations" : {
"goal_ranges" : {
"buckets" : [
{
"key" : "start-of-career",
"to" : 20.0,
"doc_count" : 3,
"age_stats" : {
"count" : 3,
"min" : 18.0,
"max" : 19.0,
"avg" : 18.333333333333332,
"sum" : 55.0
}
},
{
"key" : "mid-of-career",
"from" : 20.0,
"to" : 30.0,
"doc_count" : 13,
"age_stats" : {
"count" : 13,
"min" : 20.0,
"max" : 29.0,
"avg" : 25.846153846153847,
"sum" : 336.0
}
},
{
"key" : "end-of-cereer",
"from" : 30.0,
"doc_count" : 6,
"age_stats" : {
"count" : 6,
"min" : 31.0,
"max" : 41.0,
"avg" : 35.0,
"sum" : 210.0
}
}
]
}
}
在 Kibana 中可視化范圍非常簡單。 我們將為此使用餅圖。 如下圖所示,切片大小 count 聚合定義。 在存儲桶部分,我們需要為數據創建三個范圍。 這些范圍將是餅圖的分割部分。
Geo Distance Aggregation
使用地理距離聚合,您可以定義一個原點和到該點的一組距離范圍。然后,聚合將評估每個geo_point值到原點的距離,並確定文檔屬於哪個范圍。如果文檔的geo_point值與原點之間的距離落入該存儲桶的距離范圍內,則該文檔被視為屬於該存儲桶。
在下面的示例中,我們的原點的緯度值為46.22,經度值為-68.85。我們使用原點46.22,-68.85的字符串格式,其中第一個值定義緯度,第二個值定義經度。或者,您可以使用對象格式-{“ lat”:46.22,“ lon”:-68.85}或數組格式:[-68.85,46.22]基於GeoJson標准,其中第一個數字是lon和第二個是拉特
另外,我們以km值創建三個范圍。默認距離單位是m(米),因此我們需要在“ unit”(單位)字段中明確設置km。其他受支持的距離單位是mi(英里),in(英寸),yd(碼),cm(厘米)和mm(毫米)。
POST sports/_search
{
"size": 0,
"aggs": {
"althlete_location": {
"geo_distance": {
"field": "location",
"origin": {
"lat": 46.22,
"lon": -68.85
},
"ranges": [
{
"to": 200
},
{
"from": 200, "to": 400
},
{
"from": 400
}
]
}
}
}
}
查詢結果:
"aggregations" : {
"althlete_location" : {
"buckets" : [
{
"key" : "*-200.0",
"from" : 0.0,
"to" : 200.0,
"doc_count" : 2
},
{
"key" : "200.0-400.0",
"from" : 200.0,
"to" : 400.0,
"doc_count" : 0
},
{
"key" : "400.0-*",
"from" : 400.0,
"doc_count" : 20
}
]
}
}
結果表明,居住在距起點不超過200 km的運動員有2名,居住在距起點超過400 km的運動員有20名。
IP Range Aggregation
Elasticsearch還具有對IP范圍的內置支持。 IP聚合的工作方式與其他范圍聚合類似。 讓我們為IP地址創建索引映射,以說明此聚合的工作方式:
PUT ips
{
"mappings": {
"properties": {
"ip_addr": {
"type": "ip"
}
}
}
}
讓我們將一些專用網絡IP放入索引中。
POST ips/_bulk
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.0" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.1" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.2" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.3" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.4" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.5" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.6" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.7" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.8" }
{"index":{"_index":"ips"}}
{ "ip_addr": "172.16.0.9" }
現在,當索引中包含一些數據時,讓我們創建一個IP范圍聚合:
GET ips/_search
{
"size": 0,
"aggs": {
"ip_ranges": {
"ip_range": {
"field": "ip_addr",
"ranges": [
{
"to": "172.16.0.4"
},
{
"from": "172.16.0.4"
}
]
}
}
}
}
參考:
原文鏈接:Elastic 中國社區官方博客