天天看點

(八)elasticsearch之聚合分析的簡單介紹一、聚合分析的簡單介紹二、聚合分析之分類三、Bucket 聚合分析四、Metric 聚合分析五、Bucket + Metric 聚合分析六、pipeline 聚合分析七、聚合分析作用範圍八、排序九、聚合分析精度問題十、熱詞分析(對熱詞内容先分詞再聚合)

一、聚合分析的簡單介紹

  • 聚合分析,英文為 Aggregation,是es 除搜尋功能外提供的針對es資料做統計分析的功能。
  • es聚合分析功能豐富,提供 Bucket、Metric、Pipeline等多種分析方式,可以滿足大部分的分析需求;
  • 實時性高,所有的計算結果是即時傳回的,而Hadoop 等大資料系統一般都是 T+1 級别的。
  • 文法如下:
GET testindex/_search
{
    "size": 0,
    "aggs": {								// 關鍵詞,與query 同級
        "agg_name": {						// 自定義的聚合名稱
            "agg_type": {					// 聚合分析的定義,包含type 和 body 定義
                "agg_body"
            },
            [,"aggs": {"sub_agg"}]			// 子聚合
        },
        "agg_name2": {....}					// 可以包含多個聚合
    }
}
           

二、聚合分析之分類

  • Bucket,分桶類型,類似 SQL 中的 group by 文法;
  • Metric,名額分析類型,如計算最大值、最小值、平均值等;
  • Pipeline,管道分析類型,基于上一級的聚合分析結果進行再分析;
  • Matrix,矩陣分析類型。

三、Bucket 聚合分析

Bucket,意味 ’桶‘,即按照一定的規則将文檔配置設定到不同的桶中,達到分類的目的。

按照Bucket 的分桶政策,常見的Bucket 聚合分析如下:

  • Terms:直接按照term來分桶。如果是text 類型(需要開啟fielddata),則按照分詞後的結果分桶。
  • Range:通過制定數值的範圍内設定分桶規則
    // *-10000,10000-20000,20000-* 三個區間的文檔數聚合
    GET testinde/_search
    {
        "aggs": {
            "salary_range": {
                "range": {
                    "field": "salary",
                    "ranges": [
                        {
                        	"key": "<10000",		// 自定義key 值的名字
                            "to": 10000
                        },
                        {
                            "from": 10000,
                            "to": 20000,
                        },
                        {
                            "from": 20000
                        }
                    ]
                }
            }
        }
    }
               
  • Date Range:通過制定日期的範圍來設定分桶規則
GET testindex/_search
{
    "aggs": {
        "date_range": {
            "range": {
                "field": "birth",
                "format": "yyyy-MM-dd",					// 指定傳回結果的日期格式
                "ranges": [
                    {
                        "from": "2019-09-01",			// 指定日期範圍,可以使用date match
                        "to": "2019-09-30"
                    }
                ]
            }
        }
    }
}
           
  • Histogram:直方圖,以固定間隔的政策來分割資料
GET testindex/_search
{
    "aggs": {
        "salary_hist": {
            "histogram": {					// 關鍵詞
                "field": "salary",
                "interval": 5000,			// 指定間隔大小
                "extended_bounds": {		// 指定資料範圍
                    "min": 0,
                    "max": 50000
                }
            }
        }
    }
}
           
  • Date Histogram:針對日期的直方圖或者柱狀圖,是時序資料分析中的常用聚合分析類型
GET testindex/_search
{
    "aggs": {
        "by_year": {
            "date_histogram": {					// 關鍵詞
                "field": "birth",
                "interval": "year",			// 指定間隔大小
                "format": "yyyy"
            }
        }
    }
}
           

四、Metric 聚合分析

主要分如下2類:

  • 單值分析,隻輸出一個分析結果,常見的有min ,max ,avg ,sum , cardinality
  • 多值分析,輸出多個分析結果,常見的有stats ,extended stats ,percentile , percentile rank ,top hits

1、cardinality

集合的勢,或者基數,是指不同數值的個數。可以類比成 SQL 中的 distinct count意思。分組求和,比如某列的數值有多個不同的值。

2、stats

傳回一系列數值類型的統計值,包含了min、max、avg、sum和count。一次做了多種分析。

3、extended_stats

顧名思義,是對stats的擴充,包含了更多的統計資料,如方差、标準差等。

4、percentiles與percentile_ranks

百分位數統計。如下:

// 比如:第一行的意思是18歲以下的人數占1.0%
{
    "took": 55,
    ......
    "aggregations": {
        "per_age": {
            "1.0": 18,
            "5.0": 25,
            "25.0": 29,
            "50.0": 31,
            "75.0": 40,
            "95.0": 60,
            "99.0": 80
        }
    }
}
// 指定展示的百分位數(隻展示95%,99%,99.9%的資料)
GET testindex/_search
{
    "aggs": {
        "per_salary": {
            "percentiles": {
            	"field": "salary",
                "percents": [
                	95,
                	99,
                	99.9
                ]
            }
        }
    }
}
           

5、top_hits

一般用于分桶聚合後,擷取該桶内最比對的頂部文檔清單,即詳情資料。如下:

GET testindex/_search
{
    "aggs": {
        "group_jobs": {
            "terms": {						// 分桶聚合
                "field": "job.keyword"
            },
            "aggs": {
                "top_employee": {
                    "top_hits": {			// 關鍵詞
                        "size": 10,
                        "sort": [
                            {
                                "age": {
                                    "order": "desc"
                                }
                            }
                        ]
                    }
                }
            }
        }
    }
}
           

五、Bucket + Metric 聚合分析

Bucket 聚合分析允許通過添加子分析來進一步分析,該子分析可以是 Bucket 也可以是 Metric。

六、pipeline 聚合分析

pipeline的分析結果會輸出到原結果中,根據輸出位置的不同,可以分為2類。

1、parent 結果内嵌到現有的聚合分析結果中:

  • Derivative:計算Bucket 值的導數。
  • Moving Average:計算Bucket值的移動平均值。
  • Cumulative Sum:計算Bucket值的累計加和。

2、Sibling 結果與現有聚合分析結果同級

  • Max/Min/Avg/Sum Bucket
  • Stats/Extended Stats Bucket
  • Percentiles Bucket

七、聚合分析作用範圍

es聚合分析預設作用範圍是 query 的結果集,可以通過 filter、post_filter、global 改變其作用範圍。

filter

它是為某個聚合分析設定過濾條件的,進而在不更改整體query 語句的情況下修改作用範圍。

post_filter

作用于文檔過濾,但在聚合分析後生效,過濾輸出的結果。

global

無視query的過濾條件,基于全部文檔進行分析。比如你在query裡面進行了文檔過濾,但是global還是會基于全部文檔去分析。

八、排序

可以使用自帶的關鍵資料進行排序,比如:

  • _count 文檔數
  • _key 按照key值排序
GET testindex/_search
{
    "aggs": {
        "group_jobs": {
            "terms": {						// 分桶聚合
                "field": "job.keyword",
                "order": {					// 排序
                    "_count": "asc"
                }
            }
        }
    }
}
           

九、聚合分析精度問題

max、min這種是精确地,但是 terms 是不一定精确地。可以通過參數來優化它。

  1. 設定shard 數為1,消除資料分散的問題,但缺點比較明顯,無法承載大資料量。
  2. 合理設定 shard_size 大小,即每次從shard 上額外多擷取資料,以提升精确度。

terms 聚合傳回結果中有如下2個統計值:

  • doc_count_error_upper_bound 被遺漏的 term 可能的最大值
  • sum_other_doc_count 傳回結果 bucket 的term外,其他term的文檔總數

注:shard_size大小的設定方法

設定show_term_doc_count_error=true可以檢視每個bucket誤算的最大值。當其傳回結果的doc_count_error_upper_bound=0,則說明計算是準确的,不存在誤差。

GET testindex/_search
{
    "aggs": {
        "jobs": {
            "terms": {
                "field": "job.keyword",
                "show_term_doc_count_error": true
            }
        }
    }
}
           

shard_size預設大小如下:shard_size=size * 1.5 + 10

通過調整shard_size 的大小降低doc_count_error_upper_bound來提升準确度(随之而來的影響是增大了整體的計算量,進而降低了響應時間)

GET testindex/_search
{
    "aggs": {
        "jobs": {
            "terms": {
                "field": "job.keyword",
                "shard_size": 10,					// 關鍵詞
                "show_term_doc_count_error": true
            }
        }
    }
}
           

十、熱詞分析(對熱詞内容先分詞再聚合)

第一步,設定mapping(指定分詞器和開啟fielddata,因為你想要分詞,是以type毫無疑問是text)

PUT test
{
  "mappings": {
    "doc": {
      "properties": {
        "hello": {
          "type": "text", 
          "analyzer": "ik_max_word",
          "fielddata": true
        }
      }
    }
  }
}
           

第二步,插入測試資料

PUT test/doc/1
{
  "hello": "北京加油"
}
           

第三步,聚合查詢

GET test/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "NAME": {
      "terms": {
        "field": "hello",
        "size": 10
      }
    }
  }
}
           

結果如下:

{
  "took": 4,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "test123",
        "_type": "doc",
        "_id": "1",
        "_score": 1,
        "_source": {
          "hello": "北京加油"
        }
      }
    ]
  },
  "aggregations": {
    "NAME": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "北京",
          "doc_count": 1
        },
        {
          "key": "加油",
          "doc_count": 1
        }
      ]
    }
  }
}
           

繼續閱讀