2015-11-04 185 views
3

我使用Elasticsearch 1.7.3爲分析報告累計數據。Elasticsearch分析百分比

我有一個索引來存放每個文檔都有一個名爲'duration'的數字字段(請求需要多少毫秒)以及一個名爲'component'的字符串字段。可以有許多具有相同組件名稱的文檔。

例如,

{"component": "A", "duration": 10} 
{"component": "B", "duration": 27} 
{"component": "A", "duration": 5} 
{"component": "C", "duration": 2} 

我想產生每個組件狀態報告:

此組件的所有「持續時間」字段的總和。

A: 15 
B: 27 
C: 2 

這筆款項的比例超出所有文件持續時間的總和。在我的示例中,

A: (10+5)/(10+27+5+2) * 100 
B: 27/(10+27+5+2) * 100 
C: 2/(10+27+5+2) * 100 

每個組件的文檔佔總組件的百分比。

A: 2/4 * 100 
B: 1/4 * 100 
C: 1/4 * 100 

我該如何用Elasticsearch 1.7.3做到這一點?

+0

我的意思是,我應該怎麼做,在一個單一的查詢。 –

+0

相關:https://stackoverflow.com/questions/43508321/elasticsearch-calculate-percentage-for-each-bucket-from-total – ChrisWue

回答

2

對於ES 1.7.3,沒有辦法根據兩個不同聚合的結果來計算數據,但這可以在ES 2.0中使用pipeline aggregations來完成。

但是,你所要求的並不是在1.7.3的客戶端上做得太複雜。如果您使用下面的查詢,你會得到所有你需要得到你所期望的數字:

POST components/_search 
{ 
    "size": 0, 
    "aggs": { 
     "total_duration": { 
     "sum": { 
      "field": "duration" 
     } 
     }, 
     "components": { 
     "terms": { 
      "field": "component" 
     }, 
     "aggs": { 
      "duration_sum": { 
       "sum": { 
        "field": "duration" 
       } 
      } 
     } 
     } 
    } 
} 

結果是這樣的:

{ 
    "took": 1, 
    "timed_out": false, 
    "_shards": { 
     "total": 5, 
     "successful": 5, 
     "failed": 0 
    }, 
    "hits": { 
     "total": 4, 
     "max_score": 0, 
     "hits": [] 
    }, 
    "aggregations": { 
     "total_duration": { 
     "value": 44 
     }, 
     "components": { 
     "doc_count_error_upper_bound": 0, 
     "sum_other_doc_count": 0, 
     "buckets": [ 
      { 
       "key": "a", 
       "doc_count": 2, 
       "duration_sum": { 
        "value": 15 
       } 
      }, 
      { 
       "key": "b", 
       "doc_count": 1, 
       "duration_sum": { 
        "value": 27 
       } 
      }, 
      { 
       "key": "c", 
       "doc_count": 1, 
       "duration_sum": { 
        "value": 2 
       } 
      } 
     ] 
     } 
    } 
} 

現在,所有你需要做的是下列。我正在使用JavaScript,但您可以使用任何可以讀取JSON的其他語言來執行此操作。

var response = ...the JSON response above... 
var total_duration = response.aggregations.total_duration.value; 
var total_docs = response.hits.total; 

response.aggregations.components.buckets.forEach(function(comp_stats) { 
    // total duration for the component 
    var total_duration_comp = comp_stats.duration_sum.value; 

    // percentage duration of the component 
    var perc_duration_comp = total_duration_comp/total_duration * 100; 

    // percentage documents for the component 
    var perc_doc_comp = comp_stats.doc_count/total_docs * 100; 
}); 
+0

我想回答.. :-(。完美總結@Val – piyushGoyal

+0

謝謝Val 。我最初的查詢或多或少是相同的,但我試圖擴展它以獲取我在同一個GET查詢中需要的其餘統計信息。 我沒有意識到我不得不使用額外的代碼來獲取其餘的信息 –

+1

我已經轉移到ES 2.0,所以現在我可以使用管道聚合,哪種管道聚合將幫助我實現我的要求? –

-1

在ElasticSearch [2.X],您可以使用bucket script aggregation,這是完全滿足您的需求!

如:

{ 
    "bucket_script": { 
     "buckets_path": { 
      "my_var1": "the_sum", 
      "my_var2": "the_value_count" 
     }, 
     "script": "my_var1/my_var2" 
    } 
} 

細節:

POST /sales/_search 
{ 
    "size": 0, 
    "aggs" : { 
     "sales_per_month" : { 
      "date_histogram" : { 
       "field" : "date", 
       "interval" : "month" 
      }, 
      "aggs": { 
       "total_sales": { 
        "sum": { 
         "field": "price" 
        } 
       }, 
       "t-shirts": { 
        "filter": { 
        "term": { 
         "type": "t-shirt" 
        } 
        }, 
        "aggs": { 
        "sales": { 
         "sum": { 
         "field": "price" 
         } 
        } 
        } 
       }, 
       "t-shirt-percentage": { 
        "bucket_script": { 
         "buckets_path": { 
          "tShirtSales": "t-shirts>sales", 
          "totalSales": "total_sales" 
         }, 
         "script": "params.tShirtSales/params.totalSales * 100" 
        } 
       } 
      } 
     } 
    } 
}