該賞金到期in 4天。此問題的答案有資格獲得 150聲望獎勵。 Sean Letendre想引起更多人對這個問題的關注。
使用_searchElasticsearch的API 時,如果將 size 設定為 10,并執行avg度量聚合,則平均值將是資料集中與查詢匹配的所有值的平均值,而不僅僅是hits陣列中回傳的 10 個專案的平均值。
在另一方面,如果執行terms聚集和設定size的的terms聚集為10,然后執行avg_buckets這些聚集terms水桶將計算平均只有10桶-不是所有潛在的桶。
如何計算所有潛在存盤桶中某個欄位的平均值,但buckets陣列中仍然只有 10 個專案?
為了使我的問題更具體,請考慮以下示例:假設我是制帽商。多家商店都有我的帽子。我有一個 Elasticsearch 索引hat-sales,每當我的一頂帽子售出時,它就有一個檔案。本檔案中包括價格和出售帽子的商店。
以下是我對此進行測驗的檔案的兩個示例:
{
"type": "top",
"color": "black",
"price": 19,
"store": "Macy's"
}
{
"type": "fez",
"color": "red",
"price": 94,
"store": "Walmart"
}
如果我想找到我售出的所有帽子的平均價格,我可以運行:
GET hat-sales/_search
{
"size": 0,
"query": {
"match_all": {}
},
"aggs": {
"average_hat_price": {
"avg": {
"field": "price"
}
}
}
}
并且average_hat_price無論size設定為 0、3 還是其他值都相同。
好的,現在我想找到售出最多帽子的前 3 家商店。我還想將它們與商店出售的帽子的平均數量進行比較。所以我想做這樣的事情:
GET hat-sales/_search
{
"size": 0,
"query": {
"match_all": {}
},
"aggs": {
"by_store": {
"terms": {
"field": "store.keyword",
"size": 3
},
"aggs": {
"sales_count": {
"cardinality": {
"field": "_id"
}
}
}
},
"avg sales at a store": {
"avg_bucket": {
"buckets_path": "by_store>sales_count"
}
}
}
}
這產生了一個回應
"aggregations" : {
"by_store" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 8,
"buckets" : [
{
"key" : "Macy's",
"doc_count" : 6,
"sales_count" : {
"value" : 6
}
},
{
"key" : "Walmart",
"doc_count" : 5,
"sales_count" : {
"value" : 5
}
},
{
"key" : "Dillard's",
"doc_count" : 3,
"sales_count" : {
"value" : 3
}
}
]
},
"avg sales at a store" : {
"value" : 4.666666666666667
}
}
問題是avg sales at a store它只計算了梅西百貨、沃爾瑪和迪拉德百貨。如果我想找到的平均在所有商店,我必須設定aggs.by_store.terms.size到65536(65536,因為這是項桶的默認最大數量,我不知道先驗多少桶可能有。)這給出了結果:
"aggregations" : {
"by_store" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "Macy's",
"doc_count" : 6,
"sales_count" : {
"value" : 6
}
},
{
"key" : "Walmart",
"doc_count" : 5,
"sales_count" : {
"value" : 5
}
},
{
"key" : "Dillard's",
"doc_count" : 3,
"sales_count" : {
"value" : 3
}
},
{
"key" : "Target",
"doc_count" : 3,
"sales_count" : {
"value" : 3
}
},
{
"key" : "Harrod's",
"doc_count" : 2,
"sales_count" : {
"value" : 2
}
},
{
"key" : "Men's Warehouse",
"doc_count" : 2,
"sales_count" : {
"value" : 2
}
},
{
"key" : "Sears",
"doc_count" : 1,
"sales_count" : {
"value" : 1
}
}
]
},
"avg sales at a store" : {
"value" : 3.142857142857143
}
}
因此,每家商店售出的帽子的平均數量是 3.1,而不是 4.6。但是在buckets陣列中我只想看到前 3 家商店。
uj5u.com熱心網友回復:
您可以在沒有管道聚合的情況下實作您的目標。它有點欺騙聚合框架,但是,它有效。
這是資料設定:
PUT hat_sales
{
"mappings": {
"properties": {
"storename": {
"type": "keyword"
}
}
}
}
POST hat_sales/_bulk?refresh=true
{"index": {}}
{"storename": "foo"}
{"index": {}}
{"storename": "foo"}
{"index": {}}
{"storename": "bar"}
{"index": {}}
{"storename": "baz"}
{"index": {}}
{"storename": "baz"}
{"index": {}}
{"storename": "baz"}
這是一個棘手的查詢:
GET hat_sales/_search?size=0
{
"aggs": {
"stores": {
"terms": {
"field": "storename",
"size": 2
}
},
"average_sales_count": {
"avg_bucket": {
"buckets_path": "stores>_count"
}
},
"cheat": {
"filters": {
"filters": {
"all": {
"exists": {
"field": "storename"
}
}
}
},
"aggs": {
"count": {
"value_count": {
"field": "storename"
}
},
"unique_count": {
"cardinality": {
"field": "storename"
}
},
"total_average": {
"bucket_script": {
"buckets_path": {
"total": "count",
"unique": "unique_count"
},
"script": "params.total / params.unique"
}
}
}
}
}
}
這是對 aggs 框架的一個小濫用。但是,這個想法是你實際上想要num_stores/num_docs. 我將 限制num_docs為僅具有實際storefield名稱的檔案。
我通過使用過濾器agg進行了一些驗證,這在技術上是一個多桶 agg(盡管我只關心一個桶)。
然后我通過基數(num store)和總計數(value_count)獲得唯一計數并使用 abucket_script完成它。
總而言之,這是稍微錯位的結果:D
{
"took" : 3,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 6,
"relation" : "eq"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"cheat" : {
"buckets" : {
"all" : {
"doc_count" : 6,
"count" : {
"value" : 6
},
"unique_count" : {
"value" : 3
},
"total_average" : {
"value" : 2.0
}
}
}
},
"stores" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 1,
"buckets" : [
{
"key" : "baz",
"doc_count" : 3
},
{
"key" : "foo",
"doc_count" : 2
}
]
},
"average_sales_count" : {
"value" : 2.5
}
}
}
Note that cheat.buckets.all.total_average is 2.0 (the true average) while the old way (pipeline average) is the non-global average of 2.5
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/330906.html
