Elasticsearch聚合查詢

聚合 aggregations

聚合可以讓我們極其方便的實現(xiàn)對數(shù)據(jù)的統(tǒng)計、分析。例如:

  • 什么品牌的手機最受歡迎?
  • 這些手機的平均價格、最高價格、最低價格?
  • 這些手機每月的銷售情況如何?

1、基本概念

Elasticsearch中的聚合,包含多種類型,最常用的兩種,一個叫,一個叫度量

桶(bucket)

桶的作用,是按照某種方式對數(shù)據(jù)進行分組,每一組數(shù)據(jù)在ES中稱為一個,例如我們根據(jù)品牌對手機劃分,可以得到小米桶華為桶蘋果桶……或者我們按照年齡段對人進行劃分:010,1020,2030,3040等。

Elasticsearch中提供的劃分桶的方式有很多:

  • Date Histogram Aggregation:根據(jù)日期階梯分組,例如給定階梯為周,會自動每周分為一組
  • Histogram Aggregation:根據(jù)數(shù)值階梯分組,與日期類似
  • Terms Aggregation:根據(jù)詞條內(nèi)容分組,詞條內(nèi)容完全匹配的為一組
  • Range Aggregation:數(shù)值和日期的范圍分組,指定開始和結(jié)束,然后按段分組
  • ……

綜上所述,我們發(fā)現(xiàn)bucket aggregations 只負責對數(shù)據(jù)進行分組,并不進行計算,因此往往bucket中往往會嵌套另一種聚合:metrics aggregations即度量

度量(metrics)

分組完成以后,我們一般會對組中的數(shù)據(jù)進行聚合運算,例如求平均值、最大、最小、求和等,這些在ES中稱為度量

比較常用的一些度量聚合方式:

  • Avg Aggregation:求平均值
  • Max Aggregation:求最大值
  • Min Aggregation:求最小值
  • Percentiles Aggregation:求百分比
  • Stats Aggregation:同時返回avg、max、min、sum、count等
  • Sum Aggregation:求和
  • Top hits Aggregation:求前幾
  • Value Count Aggregation:求總數(shù)
  • ……

為了測試聚合,我們先批量導(dǎo)入一些數(shù)據(jù)
創(chuàng)建索引:

PUT /cars
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "transactions": {
      "properties": {
        "color": {
          "type": "keyword"
        },
        "make": {
          "type": "keyword"
        }
      }
    }
  }
}

注意:在ES中,需要進行聚合、排序、過濾的字段其處理方式比較特殊,因此不能被分詞。這里我們將color和make這兩個文字類型的字段設(shè)置為keyword類型,這個類型不會被分詞,將來就可以參與聚合

導(dǎo)入數(shù)據(jù)

POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "吉利", "sold" : "2020-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "長城", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "green", "make" : "比亞迪", "sold" : "2020-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "blue", "make" : "比亞迪", "sold" : "2020-07-02" }
{ "index": {}}
{ "price" : 12000, "color" : "green", "make" : "長城", "sold" : "2020-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "長安", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "red", "make" : "吉利", "sold" : "2020-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "blue", "make" : "長安", "sold" : "2020-02-12" }

2 聚合為桶

首先,我們按照 汽車的顏色color來劃分

GET /cars/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            }
        }
    }
}
  • size: 查詢條數(shù),這里設(shè)置為0,因為我們不關(guān)心搜索到的數(shù)據(jù),只關(guān)心聚合結(jié)果,提高效率
  • aggs:聲明這是一個聚合查詢,是aggregations的縮寫
    • popular_colors:給這次聚合起一個名字,任意。
      • terms:劃分桶的方式,這里是根據(jù)詞條劃分
        • field:劃分桶的字段

結(jié)果:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 8,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "popular_colors": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "red",
          "doc_count": 4
        },
        {
          "key": "blue",
          "doc_count": 2
        },
        {
          "key": "green",
          "doc_count": 2
        }
      ]
    }
  }
}
  • hits:查詢結(jié)果為空,因為我們設(shè)置了size為0
  • aggregations:聚合的結(jié)果
  • popular_colors:我們定義的聚合名稱
  • buckets:查找到的桶,每個不同的color字段值都會形成一個桶
    • key:這個桶對應(yīng)的color字段的值
    • doc_count:這個桶中的文檔數(shù)量

通過聚合的結(jié)果我們發(fā)現(xiàn),目前紅色的小車比較暢銷!

3 桶內(nèi)度量

求價格平均值的度量

GET /cars/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            },
            "aggs":{
                "avg_price": { 
                   "avg": {
                      "field": "price" 
                   }
                }
            }
        }
    }
}
  • aggs:我們在上一個aggs(popular_colors)中添加新的aggs。可見度量也是一個聚合,度量是在桶內(nèi)的聚合
  • avg_price:聚合的名稱
  • avg:度量的類型,這里是求平均值
  • field:度量運算的字段

4 桶內(nèi)嵌套桶

比如:我們想統(tǒng)計每種顏色的汽車中,分別屬于哪個制造商,按照make字段再進行分桶

GET /cars/_search
{
    "size" : 0,
    "aggs" : { 
        "popular_colors" : { 
            "terms" : { 
              "field" : "color"
            },
            "aggs":{
                "avg_price": { 
                   "avg": {
                      "field": "price" 
                   }
                },
                "maker":{
                    "terms":{
                        "field":"make"
                    }
                }
            }
        }
    }
}
  • 原來的color桶和avg計算我們不變
  • maker:在嵌套的aggs下新添一個桶,叫做maker
  • terms:桶的劃分類型依然是詞條
  • filed:這里根據(jù)make字段進行劃分

5劃分桶的其它方式

  • Date Histogram Aggregation:根據(jù)日期階梯分組,例如給定階梯為周,會自動每周分為一組
  • Histogram Aggregation:根據(jù)數(shù)值階梯分組,與日期類似
  • Terms Aggregation:根據(jù)詞條內(nèi)容分組,詞條內(nèi)容完全匹配的為一組
  • Range Aggregation:數(shù)值和日期的范圍分組,指定開始和結(jié)束,然后按段分組
    階梯分桶Histogram
    histogram是把數(shù)值類型的字段,按照一定的階梯大小進行分組。你需要指定一個階梯值(interval)來劃分階梯大小。
    如:如果你設(shè)定interval的值為200,那么階梯就會是這樣的:
    0,200,400,600,...
GET /cars/_search
{
  "size":0,
  "aggs":{
    "price":{
      "histogram": {
        "field": "price",
        "interval": 5000
      }
    }
  }
}

計算公式

key = Math.floor((value - offset) / interval) * interval + offset
  • value:就是當前數(shù)據(jù)的值
  • offset:起始偏移量,默認為0
  • interval:階梯間隔
    min_doc_count約束最少文檔數(shù)量為1,這樣文檔數(shù)量為0的桶會被過濾
GET /cars/_search
{
  "size":0,
  "aggs":{
    "price":{
      "histogram": {
        "field": "price",
        "interval": 5000,
        "min_doc_count": 1
      }
    }
  }
}

聚合查詢并且根據(jù)字段值去重

"collapse": {
    "field": "type.keyword"
  },

示例

GET xiaomi/_search
{
  "size":10,
  "_source": ["type"],
  "collapse": {
    "field": "type.keyword"
  },
  "query": {
  "term": {
    "eventType.keyword": {
       "value": "announcement"
      }
    }
  },
  "aggs" : {
    "your_aggs" : {
    "terms" : { "field" : "type.keyword" }
    }
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容