聚合 aggregations
聚合可以讓我們極其方便的實(shí)現(xiàn)對(duì)數(shù)據(jù)的統(tǒng)計(jì)铺罢、分析。例如:
- 什么品牌的手機(jī)最受歡迎会烙?
- 這些手機(jī)的平均價(jià)格负懦、最高價(jià)格、最低價(jià)格柏腻?
- 這些手機(jī)每月的銷(xiāo)售情況如何纸厉?
1、基本概念
Elasticsearch中的聚合五嫂,包含多種類(lèi)型颗品,最常用的兩種肯尺,一個(gè)叫桶
,一個(gè)叫度量
:
桶(bucket)
桶的作用躯枢,是按照某種方式對(duì)數(shù)據(jù)進(jìn)行分組则吟,每一組數(shù)據(jù)在ES中稱為一個(gè)桶
,例如我們根據(jù)品牌對(duì)手機(jī)劃分锄蹂,可以得到小米桶
氓仲、華為桶
,蘋(píng)果桶
……或者我們按照年齡段對(duì)人進(jìn)行劃分:010,1020,2030,3040等得糜。
Elasticsearch中提供的劃分桶的方式有很多:
- Date Histogram Aggregation:根據(jù)日期階梯分組敬扛,例如給定階梯為周,會(huì)自動(dòng)每周分為一組
- Histogram Aggregation:根據(jù)數(shù)值階梯分組掀亩,與日期類(lèi)似
- Terms Aggregation:根據(jù)詞條內(nèi)容分組舔哪,詞條內(nèi)容完全匹配的為一組
- Range Aggregation:數(shù)值和日期的范圍分組欢顷,指定開(kāi)始和結(jié)束槽棍,然后按段分組
- ……
綜上所述,我們發(fā)現(xiàn)bucket aggregations 只負(fù)責(zé)對(duì)數(shù)據(jù)進(jìn)行分組抬驴,并不進(jìn)行計(jì)算炼七,因此往往bucket中往往會(huì)嵌套另一種聚合:metrics aggregations即度量
度量(metrics)
分組完成以后,我們一般會(huì)對(duì)組中的數(shù)據(jù)進(jìn)行聚合運(yùn)算布持,例如求平均值豌拙、最大、最小题暖、求和等按傅,這些在ES中稱為度量
比較常用的一些度量聚合方式:
- Avg Aggregation:求平均值
- Max Aggregation:求最大值
- Min Aggregation:求最小值
- Percentiles Aggregation:求百分比
- Stats Aggregation:同時(shí)返回avg、max胧卤、min唯绍、sum、count等
- Sum Aggregation:求和
- Top hits Aggregation:求前幾
- Value Count Aggregation:求總數(shù)
- ……
為了測(cè)試聚合枝誊,我們先批量導(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中况芒,需要進(jìn)行聚合、排序叶撒、過(guò)濾的字段其處理方式比較特殊绝骚,因此不能被分詞。這里我們將color和make這兩個(gè)文字類(lèi)型的字段設(shè)置為keyword類(lèi)型祠够,這個(gè)類(lèi)型不會(huì)被分詞压汪,將來(lái)就可以參與聚合
導(dǎo)入數(shù)據(jù)
POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "吉利", "sold" : "2020-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "長(zhǎng)城", "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" : "長(zhǎng)城", "sold" : "2020-08-19" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "長(zhǎng)安", "sold" : "2020-11-05" }
{ "index": {}}
{ "price" : 80000, "color" : "red", "make" : "吉利", "sold" : "2020-01-01" }
{ "index": {}}
{ "price" : 25000, "color" : "blue", "make" : "長(zhǎng)安", "sold" : "2020-02-12" }
2 聚合為桶
首先,我們按照 汽車(chē)的顏色color
來(lái)劃分桶
GET /cars/_search
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
}
}
}
}
- size: 查詢條數(shù)古瓤,這里設(shè)置為0止剖,因?yàn)槲覀儾魂P(guān)心搜索到的數(shù)據(jù),只關(guān)心聚合結(jié)果,提高效率
- aggs:聲明這是一個(gè)聚合查詢滴须,是aggregations的縮寫(xiě)
- popular_colors:給這次聚合起一個(gè)名字舌狗,任意。
- terms:劃分桶的方式扔水,這里是根據(jù)詞條劃分
- field:劃分桶的字段
- terms:劃分桶的方式扔水,這里是根據(jù)詞條劃分
- popular_colors:給這次聚合起一個(gè)名字舌狗,任意。
結(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é)果為空痛侍,因?yàn)槲覀冊(cè)O(shè)置了size為0
- aggregations:聚合的結(jié)果
- popular_colors:我們定義的聚合名稱
- buckets:查找到的桶,每個(gè)不同的color字段值都會(huì)形成一個(gè)桶
- key:這個(gè)桶對(duì)應(yīng)的color字段的值
- doc_count:這個(gè)桶中的文檔數(shù)量
通過(guò)聚合的結(jié)果我們發(fā)現(xiàn)魔市,目前紅色的小車(chē)比較暢銷(xiāo)主届!
3 桶內(nèi)度量
求價(jià)格平均值的度量
GET /cars/_search
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
},
"aggs":{
"avg_price": {
"avg": {
"field": "price"
}
}
}
}
}
}
- aggs:我們?cè)谏弦粋€(gè)aggs(popular_colors)中添加新的aggs〈拢可見(jiàn)
度量
也是一個(gè)聚合,度量是在桶內(nèi)的聚合 - avg_price:聚合的名稱
- avg:度量的類(lèi)型君丁,這里是求平均值
- field:度量運(yùn)算的字段
4 桶內(nèi)嵌套桶
比如:我們想統(tǒng)計(jì)每種顏色的汽車(chē)中,分別屬于哪個(gè)制造商将宪,按照make
字段再進(jìn)行分桶
GET /cars/_search
{
"size" : 0,
"aggs" : {
"popular_colors" : {
"terms" : {
"field" : "color"
},
"aggs":{
"avg_price": {
"avg": {
"field": "price"
}
},
"maker":{
"terms":{
"field":"make"
}
}
}
}
}
}
- 原來(lái)的color桶和avg計(jì)算我們不變
- maker:在嵌套的aggs下新添一個(gè)桶绘闷,叫做maker
- terms:桶的劃分類(lèi)型依然是詞條
- filed:這里根據(jù)make字段進(jìn)行劃分
5劃分桶的其它方式
- Date Histogram Aggregation:根據(jù)日期階梯分組,例如給定階梯為周较坛,會(huì)自動(dòng)每周分為一組
- Histogram Aggregation:根據(jù)數(shù)值階梯分組印蔗,與日期類(lèi)似
- Terms Aggregation:根據(jù)詞條內(nèi)容分組,詞條內(nèi)容完全匹配的為一組
- Range Aggregation:數(shù)值和日期的范圍分組丑勤,指定開(kāi)始和結(jié)束华嘹,然后按段分組
階梯分桶Histogram
histogram是把數(shù)值類(lèi)型的字段,按照一定的階梯大小進(jìn)行分組法竞。你需要指定一個(gè)階梯值(interval)來(lái)劃分階梯大小耙厚。
如:如果你設(shè)定interval的值為200,那么階梯就會(huì)是這樣的:
0岔霸,200薛躬,400,600秉剑,...
GET /cars/_search
{
"size":0,
"aggs":{
"price":{
"histogram": {
"field": "price",
"interval": 5000
}
}
}
}
計(jì)算公式
key = Math.floor((value - offset) / interval) * interval + offset
- value:就是當(dāng)前數(shù)據(jù)的值
- offset:起始偏移量泛豪,默認(rèn)為0
- interval:階梯間隔
min_doc_count
約束最少文檔數(shù)量為1,這樣文檔數(shù)量為0的桶會(huì)被過(guò)濾
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" }
}
}
}