1. 程式人生 > >Elasticsearch聚合 之 Terms

Elasticsearch聚合 之 Terms

exc 定性 方式 earch des 執行 stc 默認 gen

本篇著重講解的terms聚合,它是按照某個字段中的值來分類:

比如性別有男、女,就會創建兩個桶,分別存放男女的信息。默認會搜集doc_count的信息,即記錄有多少男生,有多少女生,然後返回給客戶端,這樣就完成了一個terms得統計。

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
                },
            ]
        }
    }
}

數據的不確定性

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

舉個例子:

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

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

這樣就會造成一定的誤差,比如最後返回的前5個中,有一個叫A的,有50個文檔;B有49。但是由於每個分片獨立的保存信息,信息的分布也是不確定的。有可能第一個分片中B的信息有2個,但是沒有排到前5,所以沒有在最後合並的結果中出現。這就導致B的總數少計算了2,本來可能排到第一位,卻排到了A的後面。

size與shard_size

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

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

通過這兩個參數,如果我們想要返回前5個,size=5;shard_size可以設置大於5,這樣每個分片返回的詞條信息就會增多,相應的誤差幾率也會減小。

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" } }
            }
        }
    }
}

min_doc_count與shard_min_doc_count

聚合的字段可能存在一些頻率很低的詞條,如果這些詞條數目比例很大,那麽就會造成很多不必要的計算。
因此可以通過設置min_doc_count和shard_min_doc_count來規定最小的文檔數目,只有滿足這個參數要求的個數的詞條才會被記錄返回。

通過名字就可以看出:

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

script

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

{
    "aggs" : {
        "genders" : {
            "terms" : {
                "script" : "doc[‘gender‘].value"
            }
        }
    }
}

以及外部腳本文件:

{
    "aggs" : {
        "genders" : {
            "terms" : {
                "script" : {
                    "file": "my_script",
                    "params": {
                        "field": "gender"
                    }
                }
            }
        }
    }
}

filter

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

{
    "aggs" : {
        "tags" : {
            "terms" : {
                "field" : "tags",
                "include" : ".*sport.*",
                "exclude" : "water_.*"
            }
        }
    }
}

上面的例子中,最後的結果應該包含sport並且不包含water。
也支持數組的方式,定義包含與排除的信息:

{
    "aggs" : {
        "JapaneseCars" : {
             "terms" : {
                 "field" : "make",
                 "include" : ["mazda", "honda"]
             }
         },
        "ActiveCarManufacturers" : {
             "terms" : {
                 "field" : "make",
                 "exclude" : ["rover", "jensen"]
             }
         }
    }
}

多字段聚合

通常情況,terms聚合都是僅針對於一個字段的聚合。因為該聚合是需要把詞條放入一個哈希表中,如果多個字段就會造成n^2的內存消耗。

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

  • 1 使用腳本合並字段
  • 2 使用copy_to方法,合並兩個字段,創建出一個新的字段,對新字段執行單個字段的聚合。

collect模式

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

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

默認情況下ES會使用深度優先,不過可以手動設置成廣度優先,比如:

{
    "aggs" : {
        "actors" : {
             "terms" : {
                 "field" : "actors",
                 "size" : 10,
                 "collect_mode" : "breadth_first"
             },
            "aggs" : {
                "costars" : {
                     "terms" : {
                         "field" : "actors",
                         "size" : 5
                     }
                 }
            }
         }
    }
}

缺省值Missing value

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

{
    "aggs" : {
        "tags" : {
             "terms" : {
                 "field" : "tags",
                 "missing": "N/A" 
             }
         }
    }
}

Elasticsearch聚合 之 Terms