ElasticSearch 2 (31) - 信息聚合系列之時間處理


ElasticSearch 2 (31) - 信息聚合系列之時間處理

摘要

如果說搜索是 Elasticsearch 里最受歡迎的功能,那么按時間創建直方圖一定排在第二位。為什么需要使用時間直方圖?

版本

elasticsearch版本: elasticsearch-2.x

內容

如果說搜索是 Elasticsearch 里最受歡迎的功能,那么按時間創建直方圖一定排在第二位。為什么需要使用時間直方圖?

假設我們的數據都有時間戳,無論我們的數據是 Apache 日志事件,或是股票交易日期,還是棒球賽時間,任何與時間戳有關的數據都可以從時間直方圖里得到有價值的信息。通常我們希望根據時間來創建度量:

  • 本年度每月汽車銷量是多少?
  • 過去 12 小時股價的變化?
  • 過去一周中網站每小時內的平均響應時延是多少?

普通的直方圖通常以條狀圖表表示,日期直方圖則會轉換成折線圖用來表示時間序列。很多公司使用 Elasticsearch 只為了分析時間序列信息。date_histogram 桶正是我們想要的油條和豆漿。

date_histogram 與一般直方圖的工作方式類似,不同的是它沒有基於數值字段表示數值區間,而是基於時間范圍創建桶。因此,每個桶代表時間軸上的一段(比如:1 月 或 2.5 天)。

普通的直方圖可以展示時間嗎?

技術上講是可以的。一個普通的直方圖桶可以展示時間,但是它並不沒有與日歷相關的概念。運用 date_histogram,我們可以指定間隔為 1 月,這樣我們可以知道二月比十二月的時間短。date_histogram 還有一個優勢就是它可以與時區聯用,這讓我們可以按照用戶所處時區來定制圖形
報表,而不是服務器時間。

普通的直方圖將時間解釋成數字,這意味着我們必須以毫秒為單位指定間隔。這樣聚合對日歷時間間隔沒有任何概念,也無法使用日期信息。

我們第一個示例會創建一個簡單的折線圖表來回答問題:每個月的汽車銷量是多少?

  GET /cars/transactions/_search
  {
     "size" : 0,
     "aggs": {
        "sales": {
           "date_histogram": {
              "field": "sold",
              "interval": "month", #1
              "format": "yyyy-MM-dd" #2
           }
        }
     }
  }

#1 這個間隔是日歷語境下的值(例如:每個桶表示一個月)。

#2 為其提供一個時間格式這樣能顯示的更好看。

我們的查詢有單個聚合,每個月創建一個桶,為我們提供每月汽車銷售的數量。加上 format 參數可以讓桶的鍵值更“好看”。在內部,日期是以簡單數字形式表示的,這會讓 UI 設計師感到抓狂,不過,可以通過指定一個通用的日期格式獲得更好的格式。

響應返回如預期一樣但是有個小意外(看看能否發現它):

  {
     ...
     "aggregations": {
        "sales": {
           "buckets": [
              {
                 "key_as_string": "2014-01-01",
                 "key": 1388534400000,
                 "doc_count": 1
              },
              {
                 "key_as_string": "2014-02-01",
                 "key": 1391212800000,
                 "doc_count": 1
              },
              {
                 "key_as_string": "2014-05-01",
                 "key": 1398902400000,
                 "doc_count": 1
              },
              {
                 "key_as_string": "2014-07-01",
                 "key": 1404172800000,
                 "doc_count": 1
              },
              {
                 "key_as_string": "2014-08-01",
                 "key": 1406851200000,
                 "doc_count": 1
              },
              {
                 "key_as_string": "2014-10-01",
                 "key": 1412121600000,
                 "doc_count": 1
              },
              {
                 "key_as_string": "2014-11-01",
                 "key": 1414800000000,
                 "doc_count": 2
              }
           ]
  ...
  }

聚合被完整的呈現出來,正如看到的,我們有用來表示每個月信息的桶,每月文檔的數量信息,以及美化過后的 key_as_string

返回空桶(Returning Empty Buckets)

注意到響應中有什么奇怪的嗎?

對,正是這樣。我們缺失了一些月份的信息,date_histogram(普通 histogram 也是如此)只返回文檔數目非零的那些桶。

這表示直方圖以最小形式作為響應結果。通常,這並不是我們想要的行為。在很多應用中,我們希望直接將響應數據傳入圖形庫而不要做任何后續處理。

本質上說,即使數目為零我們也希望桶的信息能出現在結果中,可以設置兩個參數來實現這個行為:

  GET /cars/transactions/_search
  {
     "size" : 0,
     "aggs": {
        "sales": {
           "date_histogram": {
              "field": "sold",
              "interval": "month",
              "format": "yyyy-MM-dd",
              "min_doc_count" : 0, #1
              "extended_bounds" : { #2
                  "min" : "2014-01-01",
                  "max" : "2014-12-31"
              }
           }
        }
     }
  }

#1 參數強制返回空桶。

#2 參數強制返回全年數據。

兩個附加的參數會強制響應返回全年所有月份的信息,無論它們文檔數目如何。min_doc_count 哼容易理解:即使桶是空的也會強制作為結果返回。

需要對 extended_bounds 參數做些許解釋。 min_doc_count 參數強制空桶信息返回,但是 Elasticsearch 默認只會返回處於最小與最大值之間的數據。

所以如果數據在四月和七月之間,我們的桶只會表示這之間的月份(無論是不是空)。為了得到全年的信息,我們需要告訴 Elasticsearch 我們想要得到那些處於最小值和最大值之外的桶的信息。

extended_bounds 參數就是做這件事情,一旦我們增加了這兩個設置,我們就能得到可以直接傳入圖形庫的輸出,圖形的顯示如圖 Figure 37, “Cars sold over time”.

Figure 37. Cars sold over time

示例擴展(Extended Example)

正如無數次見到的那樣,可以嵌套使用桶獲得更復雜的行為。為了舉例說明,我們可以創建一個聚合按季度展示所有汽車品牌總銷售額,同時按季度、按每個汽車品牌計算銷售總額,這樣我們就能知道哪種車型能為我們的生意帶來更多收益:

  GET /cars/transactions/_search
  {
     "size" : 0,
     "aggs": {
        "sales": {
           "date_histogram": {
              "field": "sold",
              "interval": "quarter", #1
              "format": "yyyy-MM-dd",
              "min_doc_count" : 0,
              "extended_bounds" : {
                  "min" : "2014-01-01",
                  "max" : "2014-12-31"
              }
           },
           "aggs": {
              "per_make_sum": {
                 "terms": {
                    "field": "make"
                 },
                 "aggs": {
                    "sum_price": {
                       "sum": { "field": "price" } #2
                    }
                 }
              },
              "total_sum": {
                 "sum": { "field": "price" } #3
              }
           }
        }
     }
  }

#1 注意我們將間隔從 month 改成了 quarter

#2 按汽車品牌分別求和。

#3 所有汽車品牌總和。

響應返回(結果的少量片段):

  {
  ....
  "aggregations": {
     "sales": {
        "buckets": [
           {
              "key_as_string": "2014-01-01",
              "key": 1388534400000,
              "doc_count": 2,
              "total_sum": {
                 "value": 105000
              },
              "per_make_sum": {
                 "buckets": [
                    {
                       "key": "bmw",
                       "doc_count": 1,
                       "sum_price": {
                          "value": 80000
                       }
                    },
                    {
                       "key": "ford",
                       "doc_count": 1,
                       "sum_price": {
                          "value": 25000
                       }
                    }
                 ]
              }
           },
  ...
  }

我們將響應的結果作為圖形的輸入,展現總售價的折線圖,並按季度顯示每個汽車品牌的銷售總額,如圖 Figure 38, “Sales per quarter, with distribution per make”

Figure 38. Sales per quarter, with distribution per make

有限空間(The Sky’s the Limit)

這些都是顯而易見的簡單示例,但是要用圖表表示聚合總會有所限制。例如,Figure 39, “Kibana—a real time analytics dashboard built with aggregations” 圖中呈現了 Kibana 的一個儀表盤里面展示了豐富的合信息。

Figure 39. Kibana—a real time analytics dashboard built with aggregations

因為聚合的實時性,它們易於查詢、處理和交互。這對於非技術員工和分析師來說是理想的工具,因為他們可以分析數據,而知道如何創建 Hadoop 任務。

要創建像 Kibana 這樣的強大儀表盤,可能需要理解一些更高級的概念比如:限定范圍、過濾以及聚合排序。

參考

elastic.co:
Looking at Time


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM