Elasticsearch學習(4)—— 聚合查詢

http://www.cnblogs.com/xing901022/p/4947436.htmlhtml

ES中的聚合被分爲兩大類:Metric度量和bucket桶。說的通俗點,metric很像SQL中的avg、max、min等方法,而bucket就有點相似group by數組

1. Metric聚合

metric的聚合按照值的返回類型能夠分爲兩種:單值聚合 和 多值聚合spa

1.1 單值聚合

1.1.1 Sum 求和

這個聚合返回的是單個值,dsl能夠參考以下:code

"aggs" : {orm

        "intraday_return" : { "sum" : { "field" : "change" } }htm

  }blog

intraday_return是聚合的名字,同時也會做爲請求返回的id值。另外,聚合中是支持腳本的。排序

{ip

    ...內存

    "aggregations": {

        "intraday_return": {

           "value": 2.18

        }

    }

}

1.1.2 Min 求最小值

{

    "aggs" : {

        "min_price" : { "min" : { "field" : "price" } }

    }

}

1.1.3 Max 求最大值

{

    "aggs" : {

        "max_price" : { "max" : { "field" : "price" } }

    }

}

1.1.4 avg 求平均值

{

    "aggs" : {

        "avg_grade" : { "avg" : { "field" : "grade" } }

    }

}

1.1.5 cardinality 求惟一值,即不重複的字段有多少

{

    "aggs" : {

        "author_count" : {

            "cardinality" : {

                "field" : "author"

            }

        }

    }

}

1.2 多值聚合

1.2.1 percentiles 求百分比

{

    "aggs" : {

        "load_time_outlier" : {

            "percentile_ranks" : {

                "field" : "load_time", 

                "values" : [15, 30]

            }

        }

    }

}

返回結果:

{

    ...

   "aggregations": {

      "load_time_outlier": {

         "values" : {

            "15": 92,

            "30": 100

         }

      }

   }

}

1.2.2 stats 統計

{

    "aggs" : {

        "grades_stats" : { "stats" : { "field" : "grade" } }

    }

}

返回結果:

{

    ...

    "aggregations": {

        "grades_stats": {

            "count": 6,

            "min": 60,

            "max": 98,

            "avg": 78.5,

            "sum": 471

        }

    }

}

1.2.3 extend stats 擴展統計

{

    "aggs" : {

        "grades_stats" : { "extended_stats" : { "field" : "grade" } }

    }

}

返回結果:

{

    ...

    "aggregations": {

        "grade_stats": {

           "count": 9,

           "min": 72,

           "max": 99,

           "avg": 86,

           "sum": 774,

           "sum_of_squares": 67028,

           "variance": 51.55555555555556,

           "std_deviation": 7.180219742846005,

           "std_deviation_bounds": {

            "upper": 100.36043948569201,

            "lower": 71.63956051430799

           }

        }

    }

}

2. Bucket聚合

Bucket能夠理解爲一個桶,它會遍歷文檔中的內容,凡是符合要求的就放入按照要求建立的桶中。

它是按照某個字段中的值來分類:好比性別有男、女,就會建立兩個桶,分別存放男女的信息。默認會蒐集doc_count的信息,即記錄有多少男生,有多少女生,而後返回給客戶端,這樣就完成了一個terms的統計。

 2.1 terms聚合

{

    "aggs" : {

        "genders" : {

            "terms" : { "field" : "gender" }

        }

    }

}

返回結果:

{

    ...

    "aggregations" : {

        "genders" : {

            "doc_count_error_upper_bound": 0, 

            "sum_other_doc_count": 0, 

            "buckets" : [ 

                {

                    "key" : "male",

                    "doc_count" : 10

                },

                {

                    "key" : "female",

                    "doc_count" : 10

                },

            ]

        }

    }

}

2.1.1 terms聚合分析:

2.1.1.1 數據的不肯定性

使用terms聚合,結果可能帶有必定的誤差與錯誤性。

舉個例子:

咱們想要獲取name字段中出現頻率最高的前5個。

此時,客戶端向ES發送聚合請求,主節點接收到請求後,會向每一個獨立的分片發送該請求。
分片獨立的計算本身分片上的前5個name,而後返回。當全部的分片結果都返回後,在主節點進行結果的合併,再求出頻率最高的前5個,返回給客戶端。

這樣就會形成必定的偏差,好比最後返回的前5箇中,有一個叫A的,有50個文檔;B有49。可是因爲每一個分片獨立的保存信息,信息的分佈也是不肯定的。有可能第一個分片中B的信息有2個,可是沒有排到前5,因此沒有在最後合併的結果中出現。這就致使B的總數少計算了2,原本可能排到第一位,卻排到了A的後面

2.1.1.2 size與shard_size

爲了改善上面的問題,就可使用size和shard_size參數。

  • size參數規定了最後返回的term個數(默認是10個)
  • shard_size參數規定了每一個分片上返回的個數
  • 若是shard_size小於size,那麼分片也會按照size指定的個數計算

經過這兩個參數,若是咱們想要返回前5個,size=5;shard_size能夠設置大於5,這樣每一個分片返回的詞條信息就會增多,相應的偏差概率也會減少

2.1.1.3 order排序

order指定了最後返回結果的排序方式,默認是按照doc_count排序。

{

    "aggs" : {

        "genders" : {

            "terms" : {

                "field" : "gender",

                "order" : { "_count" : "asc" }

            }

        }

    }

}

也能夠按照字典方式排序:

{

    "aggs" : {

        "genders" : {

            "terms" : {

                "field" : "gender",

                "order" : { "_term" : "asc" }

            }

        }

    }

}

能夠經過order指定一個單值的metric聚合,來排序。

{

    "aggs" : {

        "genders" : {

            "terms" : {

                "field" : "gender",

                "order" : { "avg_height" : "desc" }

            },

            "aggs" : {

                "avg_height" : { "avg" : { "field" : "height" } }

            }

        }

    }

}

多值的Metric聚合,要指定使用的多值字段:

{

    "aggs" : {

        "genders" : {

            "terms" : {

                "field" : "gender",

                "order" : { "height_stats.avg" : "desc" }

            },

            "aggs" : {

                "height_stats" : { "stats" : { "field" : "height" } }

            }

        }

    }

}

2.1.1.4 min_doc_count與shard_min_doc_count

聚合的字段可能存在一些頻率很低的詞條,若是這些詞條數目比例很大,那麼就會形成不少沒必要要的計算。
所以能夠經過設置min_doc_count和shard_min_doc_count來規定最小的文檔數目,只有知足這個參數要求的個數的詞條纔會被記錄返回。

經過名字就能夠看出:

  • min_doc_count:規定了最終結果的篩選
  • shard_min_doc_count:規定了分片中計算返回時的篩選

2.1.1.5 script

桶聚合也支持腳本的使用:

{

    "aggs" : {

        "genders" : {

            "terms" : {

                "script" : "doc['gender'].value"

            }

        }

    }

}

以及外部腳本文件:

{

    "aggs" : {

        "genders" : {

            "terms" : {

                "script" : {

                    "file": "my_script",

                    "params": {

                        "field": "gender"

                    }

                }

            }

        }

    }

}

2.1.1.6 filter

filter字段提供了過濾的功能,使用兩種方式:include能夠過濾出包含該值的文檔;相反則使用exclude。

{

    "aggs" : {

        "tags" : {

            "terms" : {

                "field" : "tags",

                "include" : ".*sport.*",

                "exclude" : "water_.*"

            }

        }

    }

}

2.1.2 多字段聚合

一般狀況,terms聚合都是僅針對於一個字段的聚合。由於該聚合是須要把詞條放入一個哈希表中,若是多個字段就會形成n^2的內存消耗。

不過,對於多字段,ES也提供了下面兩種方式:

    1. 使用腳本合併字段

    2. 使用copy_to方法,合併兩個字段,建立出一個新的字段,對新字段執行單個字段的聚合。

例如:實現 select SEX,PROF,COUNT(*) from table group by SEX,PROF

{

    "size": 0,

    "query": {

        "match_all": {}

    },

    "aggs": {

        "sexprof": { //使用腳本合併字段並對新字段執行單字段的聚合

            "terms": {

                "script": {

                    "inline": "doc['SEX.keyword'].value +'-split-'+ doc['PROF.keyword'].value "

                }

            }

        }

    }

}

獲得的結果:

{
    "aggregations": {
        "sexprof": {
            "doc_count_error_upper_bound": 5,
            "sum_other_doc_count": 379,
            "buckets": [
                {
                    "key": "女-split-助教",
                    "doc_count": 2
                },
                {
                    "key": "男-split-講師",
                    "doc_count": 1
                },
                {
                    "key": "男-split-教授",
                    "doc_count": 1
                }
            ]
        }
    }
}

2.1.3 collect模式

對於子聚合的計算,有兩種方式:

  • depth_first 直接進行子聚合的計算
  • breadth_first 先計算出當前聚合的結果,針對這個結果在對子聚合進行計算。

默認狀況下ES會使用深度優先,不過能夠手動設置成廣度優先,好比:

{

    "aggs" : {

        "actors" : {

             "terms" : {

                 "field" : "actors",

                 "size" : 10,

                 "collect_mode" : "breadth_first"

             },

            "aggs" : {

                "costars" : {

                     "terms" : {

                         "field" : "actors",

                         "size" : 5

                     }

                 }

            }

         }

    }

}

2.1.4 缺省值Missing value

缺省值指定了缺省的字段的處理方式:

{

    "aggs" : {

        "tags" : {

             "terms" : {

                 "field" : "tags",

                 "missing": "N/A" 

             }

         }

    }

}

2.2 Histogram 直方圖聚合

Elasticsearch支持最直方圖聚合,它在數字字段自動建立桶,並會掃描所有文檔,把文檔放入相應的桶中。這個數字字段既能夠是文檔中的某個字段,也能夠經過腳本建立得出的。

2.2.1 桶的篩選規則

2.2.1.1 min_doc_count過濾

返回document數量大於等於1 的直方圖聚合

{

    "aggs" : {

        "prices" : {

            "histogram" : {

                "field" : "price",

                "interval" : 50,

                "min_doc_count" : 1

            }

        }

    }

}

2.2.1.2 extend_bounds,指定最小值和最大值邊界

默認狀況下,ES中的histogram聚合起始都是自動的,好比price字段,若是沒有商品的價錢在0-5之間,0這個桶就不會顯示。若是最便宜的商品是11,那麼第一個桶就是10.

能夠經過設置extend_bounds強制規定最小值和最大值,可是要求必須min_doc_count不能大於0,否則即使是規定了邊界,也不會返回。

能夠經過設置extend_bounds強制規定最小值和最大值,可是要求必須min_doc_count不能大於0,否則即使是規定了邊界,也不會返回。

2.2.1.3 order排序

排序大同小異,能夠按照_key,_count,指定排序的聚合進行排序

{

    "aggs" : {

        "prices" : {

            "histogram" : {

                "field" : "price",

                "interval" : 50,

                "order" : { "_key" : "desc" }

            }

        }

    }

}

2.2.1.4 keyed設置返回的方式

正常返回的數據如上面所示,是按照數組的方式返回。若是要按照名字返回,能夠設置keyed爲true。

以前的返回方式:

設置keyed爲true:

{

    "aggs" : {

        "prices" : {

            "histogram" : {

                "field" : "price",

                "interval" : 50,

                "keyed" : true

            }

        }

    }

}

 返回的數據爲:

{
    "aggregations": {
        "prices": {
            "buckets": {
                "0": {
                    "key": 0,
                    "doc_count": 2
                },
                "50": {
                    "key": 50,
                    "doc_count": 4
                },
                "150": {
                    "key": 150,
                    "doc_count": 3
                }
            }
        }
    }
}

2.2.1.5 缺省的值

缺省值經過MissingValue設置:

{

    "aggs" : {

        "quantity" : {

             "histogram" : {

                 "field" : "quantity",

                 "interval": 10,

                 "missing": 0 

             }

         }

    }

}

 

2.3 Date Histogram聚合 

Date histogram的用法與histogram差很少,只不過區間上支持了日期的表達式。

{

 "aggs":{

    "articles_over_time":{

        "date_histogram":{

            "field":"date",

            "interval":"month"

            }

        }

    }

}

interval字段支持多種關鍵字:`year`, `quarter`, `month`, `week`, `day`, `hour`, `minute`, `second`

也支持對這些關鍵字進行擴展使用,好比一個半小時能夠定義成以下::

{

    "aggs":{

        "articles_over_time":{

            "date_histogram":{

                "field":"date",

                "interval":"1.5h"

                "format":"yyyy-MM-dd" //對返回結果進行格式化

                }

            }

        }

}

2.3.1 time_zone時區的用法

在es中日期支持時區的表示方法,這樣就至關於東八區的時間。

{

    "aggs":{

        "by_day":{

            "date_histogram":{

                "field":"date",

                "interval":"day",

                "time_zone":"+08:00"

            }

        }

    }

}

2.3.2 offset 使用偏移值,改變時間區間

默認狀況是從凌晨0點到午夜24:00,若是想改變時間區間,能夠經過下面的方式,設置偏移值:

{

"aggs":{

    "by_day":{

        "date_histogram":{

            "field":"date",

            "interval":"day",

            "offset":"+6h"

            }

        }

    }

}

2.3.3 Missing Value缺省字段

當遇到沒有值的字段,就會按照缺省字段missing value來計算。

對於其餘的一些用法,這裏就不過多贅述了,好比腳本、Order、min_doc_count過濾,extended_bounds等都是支持的。

{

  "aggs": {

    "missing_address": {

      "missing": {

        "field": "address"

      }

    }

  }

}

結果只返回一個桶

2.4 嵌套聚合

{

   "aggs":{

      "color_type_max":{

         "terms":{ 

            "field": "color"

         },

         "aggs":{

            "max_age": {

               "max": { 

                 "field" : "age"

               }

             }

         }

      },

      "color_type_min":{

         "terms":{ 

            "field": "color"

         },

         "aggs":{

            "min_age": {

               "min": { 

                 "field" : "age"

               }

             }

         }

      }

   }

}

相關文章
相關標籤/搜索