此處簡單記錄一下bucket
聚合下的terms
聚合。記錄一下terms
聚合的各種用法,以及各種注意事項,防止以後忘記。
PUT /index_person
{
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "keyword"
},
"sex": {
"type": "keyword"
},
"age": {
"type": "integer"
},
"province": {
"type": "keyword"
},
"address": {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
PUT /_bulk
{"create":{"_index":"index_person","_id":1}}
{"id":1,"name":"張三","sex":"男","age":20,"province":"湖北","address":"湖北省黃岡市羅田縣匡河鎮"}
{"create":{"_index":"index_person","_id":2}}
{"id":2,"name":"李四","sex":"男","age":19,"province":"江蘇","address":"江蘇省南京市"}
{"create":{"_index":"index_person","_id":3}}
{"id":3,"name":"王武","sex":"女","age":25,"province":"湖北","address":"湖北省武漢市江漢區"}
{"create":{"_index":"index_person","_id":4}}
{"id":4,"name":"趙六","sex":"女","age":30,"province":"北京","address":"北京市東城區"}
{"create":{"_index":"index_person","_id":5}}
{"id":5,"name":"錢七","sex":"女","age":16,"province":"北京","address":"北京市西城區"}
{"create":{"_index":"index_person","_id":6}}
{"id":6,"name":"王八","sex":"女","age":45,"province":"北京","address":"北京市朝陽區"}
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_sex": {
"terms": {
"field": "province",
"size": 2
}
}
}
}
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_sex": {
"terms": {
"field": "province",
"size": 2,
"order": {
"_count": "asc"
}
}
}
}
}
注意: 不推薦使用 _count:asc
來統計,會導致統計結果不準
,看下方的總結章節。
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_sex": {
"terms": {
"field": "age",
"size": 2,
"order": {
"_key": "asc"
}
}
}
}
}
注意: 這種根據欄位值來排序,聚合的結果是正確的。
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_sex": {
"terms": {
"field": "province",
"order": {
"min_age": "asc"
}
},
"aggs": {
"min_age": {
"min": {
"field": "age"
}
}
}
}
}
}
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_sex": {
"terms": {
"field": "province",
"order": {
"min_age.min": "asc"
}
},
"aggs": {
"min_age": {
"stats": {
"field": "age"
}
}
}
}
}
}
注意: 子聚合排序一般也是不準的,但是如果是根據子聚合的最大值倒序
和最小值升序
又是準的。
GET /index_person/_search
{
"size": 0,
"runtime_mappings": {
"province_sex": {
"type": "keyword",
"script": """
String province = doc['province'].value;
String address = doc['address.keyword'].value;
if(address.contains('黃岡市')){
emit('黃岡市');
}else{
emit(province);
}
"""
}
},
"aggs": {
"agg_sex": {
"terms": {
"field": "province_sex"
}
}
}
}
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_province": {
"terms": {
"field": "province",
"include": ".*北.*",
"exclude": ["湖北"]
}
}
}
}
注意: 當是字串時,可以寫正規表示式,當是陣列時,需要寫具體的值。
GET /index_person/_search
{
"size": 0,
"aggs": {
"genres_and_products": {
"multi_terms": {
"size": 10,
"shard_size": 25,
"order":{
"max_age": "desc"
},
"terms": [
{
"field": "province",
"missing": "defaultProvince"
},
{
"field": "sex"
}
]
},
"aggs": {
"max_age": {
"max": {
"field": "age"
}
}
}
}
}
}
注意: terms
聚合預設不支援多欄位聚合,需要藉助別的方式。此處使用multi terms
來實現多欄位聚合。
GET /index_person/_search
{
"size": 0,
"aggs": {
"agg_province": {
"terms": {
"field": "province"
}
},
"agg_sex":{
"terms": {
"field": "sex",
"size": 10
}
}
}
}
一般情況下,只有如下幾種欄位型別可以進行聚合操作 keyword
,numeric
,ip
,boolean
和binary
型別的欄位。text
型別的欄位預設情況下是不可以進行聚合的,如果需要聚合,需要開啟fielddata
。
如果我們只想返回100
或1000
個唯一結果,可以增大size
引數的值。但是如果我們想返回所有的,那麼推薦使用 composite aggregation
我們通過terms
聚合到的結果是一個大概的結果,不一定是完全正確的。
為什麼?
.
舉個例子: 如果我們的叢集有3個分片,此處我們想返回值最高的5個統計。即size=5
,假設先不考慮shard_size
引數,那麼此時每個節點會返回值最高的5個統計,然後再次聚合,返回,返回最終值最高的5個。這個貌似沒什麼問題,但是因為我們的資料是分佈es的各個節點上的,可能某個統計項(北京市的使用者數
),在A節點是是排名前5,但是在B節點上不是排名前5,那麼最終的統計結果是否是就會漏統計了。
如何解決:
我們可以讓es在每個節點上多返回幾個結果,比如
:我們的size=5
,那麼我們每個節點就返回 size * 1.5 + 10
個結果,那麼誤差相應的就會減少。 而這個size * 1.5 + 10
就是shard_size
的值,當然我們也可以手動指定,但一般需要比size的值大。
預設情況下,使用的是 _count
倒序的,但是我們可以指定成升序,但是這是不推薦的,會導致錯誤結果。如果我們想要升序,可以使用 rare_terms
聚合。
使用欄位值排序,不管是正序還是倒序,結果是準確的。
本文來自部落格園,作者:huan1993,轉載請註明原文連結:https://www.cnblogs.com/huan1993/p/16886488.html