2015-11-04 72 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" 
        } 
       } 
      } 
     } 
    } 
}