Elasticsearch聚合查詢(xún)(一)

在Mysql中,我們可以獲取一組數(shù)據(jù)的 最大值(Max)、最小值(Min)。同樣我們能夠?qū)@組數(shù)據(jù)進(jìn)行 分組(Group)。那么對(duì)于Elasticsearch中,我們也可以實(shí)現(xiàn)同樣的功能。

官方對(duì)聚合有四個(gè)關(guān)鍵字: Metric(指標(biāo))、Bucketing(桶)、Matrix(矩陣)、Pipeline(管道)。

一、聚合概念

1. ES聚合分析是什么?

概念 Elasticsearch除全文檢索功能外提供的針對(duì)Elasticsearch數(shù)據(jù)做統(tǒng)計(jì)分析的功能。它的實(shí)時(shí)性高,所有的計(jì)算結(jié)果都是即時(shí)返回。
Elasticsearch將聚合分析主要分為如下4類(lèi):

Metric(指標(biāo)):   指標(biāo)分析類(lèi)型,如計(jì)算最大值、最小值、平均值等等 (對(duì)桶內(nèi)的文檔進(jìn)行聚合分析的操作)
Bucket(桶):     分桶類(lèi)型,類(lèi)似SQL中的GROUP BY語(yǔ)法 (滿(mǎn)足特定條件的文檔的集合)
Pipeline(管道): 管道分析類(lèi)型,基于上一級(jí)的聚合分析結(jié)果進(jìn)行在分析
Matrix(矩陣):   矩陣分析類(lèi)型(聚合是一種面向數(shù)值型的聚合,用于計(jì)算一組文檔字段中的統(tǒng)計(jì)信息)

2.ES聚合分析查詢(xún)的寫(xiě)法

在查詢(xún)請(qǐng)求體中以aggregations節(jié)點(diǎn)按如下語(yǔ)法定義聚合分析:

"aggregations" : {
    "<aggregation_name>" : {                                 <!--聚合的名字 -->
        "<aggregation_type>" : {                               <!--聚合的類(lèi)型 -->
            <aggregation_body>                                 <!--聚合體:對(duì)哪些字段進(jìn)行聚合 -->
        }
        [,"meta" : {  [<meta_data_body>] } ]?               <!--元 -->
        [,"aggregations" : { [<sub_aggregation>]+ } ]?   <!--在聚合里面在定義子聚合 -->
    }
    [,"<aggregation_name_2>" : { ... } ]*                     <!--聚合的名字 -->
}

說(shuō)明aggregations 也可簡(jiǎn)寫(xiě)為 aggs

3、指標(biāo)(metric)和 桶(bucket)

雖然Elasticsearch有四種聚合方式,但在一般實(shí)際開(kāi)發(fā)中,用到的比較多的就是Metric和Bucket。

(1) 桶(bucket)  
a、簡(jiǎn)單來(lái)說(shuō)桶就是滿(mǎn)足特定條件的文檔的集合。
b、當(dāng)聚合開(kāi)始被執(zhí)行,每個(gè)文檔里面的值通過(guò)計(jì)算來(lái)決定符合哪個(gè)桶的條件,如果匹配到,文檔將放入相應(yīng)的桶并接著開(kāi)始聚合操作。
c、桶也可以被嵌套在其他桶里面。

(2)指標(biāo)(metric)
a、桶能讓我們劃分文檔到有意義的集合,但是最終我們需要的是對(duì)這些桶內(nèi)的文檔進(jìn)行一些指標(biāo)的計(jì)算。分桶是一種達(dá)到目的地的手段:它提供了一種給文檔分組的方法來(lái)讓我們可以計(jì)算感興趣的指標(biāo)。
b、大多數(shù)指標(biāo)是簡(jiǎn)單的數(shù)學(xué)運(yùn)算(如:最小值、平均值、最大值、匯總),這些是通過(guò)文檔的值來(lái)計(jì)算的。

二、指標(biāo)(Metric)詳解

官網(wǎng): 指標(biāo)聚合官網(wǎng)文檔:Metric

Metric聚合分析分為單值分析和多值分析兩類(lèi):

#1、單值分析,只輸出一個(gè)分析結(jié)果
min,max,avg,sum,cardinality
#2、多值分析,輸出多個(gè)分析結(jié)果
stats,extended_stats,percentile,percentile_rank,top hits

1、Avg(平均值)

計(jì)算從聚合文檔中提取的數(shù)值的平均值。

POST /exams/_search?size=0
{
    "aggs" : {
        "avg_grade" : { "avg" : { "field" : "grade" } }
    }
}

2、Max(最大值)

計(jì)算從聚合文檔中提取的數(shù)值的最大值。

POST /sales/_search?size=0
{
    "aggs" : {
        "max_price" : { "max" : { "field" : "price" } }
    }
}

3、Min(最小值)

計(jì)算從聚合文檔中提取的數(shù)值的最小值。

POST /sales/_search?size=0
{
    "aggs" : {
        "min_price" : { "min" : { "field" : "price" } }
    }
}

4、Sum(總和)

計(jì)算從聚合文檔中提取的數(shù)值的總和。

POST /sales/_search?size=0
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "match" : { "type" : "hat" }
            }
        }
    },
    "aggs" : {
        "hat_prices" : { "sum" : { "field" : "price" } }
    }
}

5、 Cardinality(唯一值)

cardinality 求唯一值,即不重復(fù)的字段有多少(相當(dāng)于mysql中的distinct)

POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : {
                "field" : "type"
            }
        }
    }
}

6、Stats

stats 統(tǒng)計(jì),請(qǐng)求后會(huì)直接顯示多種聚合結(jié)果

POST /exams/_search?size=0
{
    "aggs" : {
        "grades_stats" : { "stats" : { "field" : "grade" } }
    }
}

返回

{
    ...
    "aggregations": {
        "grades_stats": {
            "count": 2,
            "min": 50.0,
            "max": 100.0,
            "avg": 75.0,
            "sum": 150.0
        }
    }
}

7、Percentiles

對(duì)指定字段的值按從小到大累計(jì)每個(gè)值對(duì)應(yīng)的文檔數(shù)的占比,返回指定占比比例對(duì)應(yīng)的值。

1)默認(rèn)取百分比

默認(rèn)按照[ 1, 5, 25, 50, 75, 95, 99 ]來(lái)統(tǒng)計(jì)

GET latency/_search
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time" 
            }
        }
    }
}

返回結(jié)果可以理解為:占比為50%的文檔的age值 <= 445,或反過(guò)來(lái):age<=445的文檔數(shù)占總命中文檔數(shù)的50%

{
    ...
   "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
         }
      }
   }
}

2)指定分位值

GET latency/_search
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time",
                "percents" : [95, 99, 99.9] 
            }
        }
    }
}
  1. Keyed Response

默認(rèn)情況下,keyed標(biāo)志設(shè)置為true,它將唯一的字符串鍵與每個(gè)存儲(chǔ)桶相關(guān)聯(lián),并將范圍作為哈希而不是數(shù)組返回。

GET latency/_search
{
    "size": 0,
    "aggs": {
        "load_time_outlier": {
            "percentiles": {
                "field": "load_time",
                "keyed": false
            }
        }
    }
}

返回結(jié)果

{
    ...
    "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
                }
            ]
        }
    }
}

8、 Percentile Ranks

上面是通過(guò)百分比求文檔值,這里通過(guò)文檔值求百分比。

GET latency/_search
{
    "size": 0,
    "aggs" : {
        "load_time_ranks" : {
            "percentile_ranks" : {
                "field" : "load_time", 
                "values" : [500, 600]
            }
        }
    }
}

返回結(jié)果

{
    ...
   "aggregations": {
      "load_time_ranks": {
         "values" : {
            "500.0": 55.1,
            "600.0": 64.0
         }
      }
   }
}

結(jié)果說(shuō)明:時(shí)間小于500的文檔占比為55.1%,時(shí)間小于600的文檔占比為64%,

9、Top Hits

一般用于分桶后獲取該桶內(nèi)匹配前n的文檔列表

POST /sales/_search?size=0
{
    "aggs": {
        "top_tags": {
            "terms": {
                "field": "type",  #根據(jù)type進(jìn)行分組 每組顯示前3個(gè)文檔
                "size": 3
            },
            "aggs": {
                "top_sales_hits": {
                    "top_hits": {
                        "sort": [
                            {
                                "date": { 
                                    "order": "desc"  #按照時(shí)間進(jìn)行倒敘排序
                                }
                            }
                        ],
                        "_source": {
                            "includes": [ "date", "price" ] #只顯示文檔指定字段
                        },
                        "size" : 1
                    }
                }
            }
        }
    }
}

三、示例

下面會(huì)針對(duì)上面官方文檔的例子進(jìn)行舉例說(shuō)明。

1、添加測(cè)試數(shù)據(jù)

1)創(chuàng)建索引

DELETE /employees
PUT /employees/
{
  "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "gender" : {
          "type" : "keyword"
        },
        "job" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 50
            }
          }
        },
        "name" : {
          "type" : "keyword"
        },
        "salary" : {
          "type" : "integer"
        }
      }
    }
}

2)添加數(shù)據(jù)

添加10條數(shù)據(jù),每條數(shù)據(jù)包含:姓名、年齡、工作、性別、薪資

PUT /employees/_bulk
{ "index" : {  "_id" : "1" } }
{ "name" : "Emma","age":32,"job":"Product Manager","gender":"female","salary":35000 }
{ "index" : {  "_id" : "2" } }
{ "name" : "Underwood","age":41,"job":"Dev Manager","gender":"male","salary": 50000}
{ "index" : {  "_id" : "3" } }
{ "name" : "Tran","age":25,"job":"Web Designer","gender":"male","salary":18000 }
{ "index" : {  "_id" : "4" } }
{ "name" : "Rivera","age":26,"job":"Web Designer","gender":"female","salary": 22000}
{ "index" : {  "_id" : "5" } }
{ "name" : "Rose","age":25,"job":"QA","gender":"female","salary":18000 }
{ "index" : {  "_id" : "6" } }
{ "name" : "Lucy","age":31,"job":"QA","gender":"female","salary": 25000}
{ "index" : {  "_id" : "7" } }
{ "name" : "Byrd","age":27,"job":"QA","gender":"male","salary":20000 }
{ "index" : {  "_id" : "8" } }
{ "name" : "Foster","age":27,"job":"Java Programmer","gender":"male","salary": 20000}
{ "index" : {  "_id" : "9" } }
{ "name" : "Gregory","age":32,"job":"Java Programmer","gender":"male","salary":22000 }
{ "index" : {  "_id" : "10" } }
{ "name" : "Bryant","age":20,"job":"Java Programmer","gender":"male","salary": 9000}

2、求薪資最低值

POST employees/_search
{
  "size": 0,
  "aggs": {
    "min_salary": {
      "min": {
        "field":"salary"
      }
    }
  }
}

返回

3、找到最低、最高和平均工資

POST employees/_search
{
  "size": 0,
  "aggs": {
    "max_salary": {
      "max": {
        "field": "salary"
      }
    },
    "min_salary": {
      "min": {
        "field": "salary"
      }
    },
    "avg_salary": {
      "avg": {
        "field": "salary"
      }
    }
  }
}

4、一個(gè)聚合,輸出多值

POST employees/_search
{
  "size": 0,
  "aggs": {
    "stats_salary": {
      "stats": {
        "field":"salary"
      }
    }
  }
}

返回

5、求一共有多少工作類(lèi)型

POST employees/_search
{
  "size": 0,
  "aggs": {
    "cardinate": {
      "cardinality": {
        "field": "job.keyword"
      }
    }
  }
}

返回

注意 我們需要把job的類(lèi)型為keyword類(lèi)型,這樣就不會(huì)分詞,把它當(dāng)成一個(gè)整體。

6、查看中位數(shù)的薪資

POST employees/_search
{
    "size": 0,
    "aggs": {
        "load_time_outlier": {
            "percentiles": {
                "field": "salary",
                 "percents" : [50, 99],
                "keyed": false
            }
        }
    }
}

返回

發(fā)現(xiàn)這些工作的中位數(shù)是:21000元。

7、取每個(gè)工作類(lèi)型薪資最高的數(shù)據(jù)

多層嵌套 根據(jù)工作類(lèi)型分桶,然后按照性別分桶,計(jì)算每個(gè)桶中工資的最高的薪資。

POST employees/_search
{
  "size": 0,
  "aggs": {
    "Job_gender_stats": {
      "terms": {
        "field": "job.keyword"
      },
      "aggs": {
        "gender_stats": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "salary_stats": {
              "max": {
                "field": "salary"
              }
            }
          }
        }
      }
    }
  }
}

返回

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容