Title:ElasticSearch實戰系列四: ElasticSearch的聚合查詢基礎使用教程之度量(Metric)聚合html
在上上一篇中介紹了ElasticSearch實戰系列三: ElasticSearch的JAVA API使用教程,介紹了ElasticSearch Java API基礎的語法,基本的增刪改查(對應SQL語句), 本篇則來介紹一下ElasticSearch 聚合查詢的使用JAVA API 和 DSL語句的使用 。java
聚合框架有助於基於搜索查詢提供聚合數據。它基於稱爲聚合的簡單構建塊,能夠進行組合以構建複雜的數據摘要。
聚合能夠看做是在一組文檔上創建分析信息的工做單元。執行的上下文定義此文檔集是什麼(例如,頂級聚合在搜索請求的已執行查詢/過濾器的上下文中執行)。
有許多不一樣類型的聚合,每種聚合都有本身的目的和輸出。爲了更好地理解這些類型,一般更容易將它們分爲四個主要家族:git
Metric:github
在一組文檔上跟蹤和計算指標的聚合。這些值一般是從文檔的字段中提取的(使用字段數據),但也可使用腳本生成。框架
Bucketing:elasticsearch
生成存儲桶的一組聚合,其中每一個存儲桶都與一個鍵和一個文檔條件相關聯。執行聚合時,將對上下文中的每一個文檔評估全部存儲桶條件,而且當條件匹配時,該文檔將被視爲「落入」相關存儲桶。到聚合過程結束時,咱們將獲得一個存儲桶列表-每一個存儲桶都有一組「屬於」的文檔。ide
Matrix:測試
操做多個字段並根據從請求的文檔字段中提取的值生成矩陣結果的集合。與Metric和Bucketing不一樣,這個聚合不支持腳本!fetch
Pipeline:ui
它聚合其餘聚合的輸出及其相關的Metric。
因爲每一個存儲桶有效地定義了一個文檔集(全部文件都屬於該存儲桶),所以能夠潛在地在存儲桶級別關聯聚合,而且這些聚合將在該存儲桶的上下文中執行。這就是聚合真正的力量所在:聚合能夠嵌套!
存儲桶聚合能夠具備子聚合(存儲桶或指標)。子聚合將針對其父聚合生成的存儲桶進行計算。嵌套聚合的級別/深度沒有硬性限制(能夠將一個聚合嵌套在「父」聚合下,該「父」聚合自己是另外一種更高級別的聚合的子聚合)。
聚合做用於double數據的表示形式。所以,當運行絕對值大於的多頭時,結果多是近似的2^53。
數值指標聚合是一種特殊類型的指標聚合,可輸出數值。一些聚合輸出單個數值度量(例如avg)並被稱爲single-value numeric metrics aggregation,其餘聚合則生成多個度量(例如stats)並被稱爲multi-value numeric metrics aggregation。當這些值充當某些存儲桶聚合的直接子聚合(某些存儲桶聚合使您能夠基於每一個存儲桶中的數字度量對返回的存儲桶進行排序)時,單值和多值數字度量聚合之間的區別將發揮做用。
度量(Metric)聚合在ElasticSearch官方文檔中有很中聚合,這裏我只列舉咱們最經常使用的幾個聚合示例。
計算的平均個從彙集的文檔中提取數值。這些值能夠從文檔中的特定數字字段中提取,也能夠由提供的腳本生成。
這裏咱們用一個示例來進行說明,獲得一個班級的學生分數平均分數。
DSL語句示例:
POST /student/_search?size=0 { "aggs" : { "avg_grade" : { "avg" : { "field" : "grade" } } } }
注: grade 字段類型必須是整型
固然,若是成績還包含權重(weight)的話,咱們能夠爲其添加權重.
權重: 在計算常規平均值時,每一個數據點都具備相等的``權重''...它對最終值的貢獻均等。能夠理解爲權重值越大,就越靠前,加權公式爲: ∑(value * weight) / ∑(weight).
DSL語句示例:
POST /student/_search { "size": 0, "aggs" : { "weighted_grade": { "weighted_avg": { "value": { "field": "grade" }, "weight": { "field": "weight" } } } } }
這裏咱們用一個示例來進行說明,獲得班級的最高分和最低分。
DSL語句示例:
POST /student/_search?size=0 { "aggs" : { "max_grade" : { "max" : { "field" : "grade" } } } } POST /student/_search?size=0 { "aggs" : { "min_grade" : { "min" : { "field" : "grade" } } } }
獲得某字段總和的值。
DSL語句示例:
POST /student/_search?size=0 { "aggs" : { "sum_grade" : { "sum" : { "field" : "grade" } } } }
一個top_hits指標聚合不斷被聚合跟蹤最相關的文檔。該聚合器旨在用做子聚合器,以即可以按存儲分區彙總最匹配的文檔。該top_hits聚合器能夠有效地經過某些字段經由剷鬥聚合器用於將結果集。一個或多個存儲桶聚合器肯定將結果集切成哪些屬性。
選件
這裏咱們依舊經過一個示例來進行說明。
根據grade(成績)降序取前2條數據,字段只包含grade(成績)和name(姓名)。
DSL語句示例:
POST /student/_search?size=0 { "aggs": { "top_tags": { "terms": { "field": "grade", "size": 2 }, "aggs": { "top_sales_hits": { "top_hits": { "sort": [ { "grade": { "order": "desc" } } ], "_source": { "includes": [ "grade", "name" ] }, "size" : 1 } } } } } }
/** * @Author pancm * @Description 平均聚合查詢測試用例 * @Date 2019/4/1 * @Param [] * @return void **/ private static void avgSearch() throws IOException { String buk="t_grade_avg"; //直接求平均數 AggregationBuilder aggregation = AggregationBuilders.avg(buk).field("grade"); logger.info("求班級的平均分數:"); agg(aggregation,buk); } private static void maxSearch() throws IOException{ String buk="t_grade"; AggregationBuilder aggregation = AggregationBuilders.max(buk).field("grade"); logger.info("求班級的最高分數:"); agg(aggregation,buk); } private static void sumSearch() throws IOException{ String buk="t_grade"; AggregationBuilder aggregation = AggregationBuilders.sum(buk).field("grade"); logger.info("求班級的總分數:"); agg(aggregation,buk); } private static SearchResponse search(AggregationBuilder aggregation) throws IOException { SearchRequest searchRequest = new SearchRequest(); searchRequest.indices("student"); searchRequest.types("_doc"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //不須要解釋 searchSourceBuilder.explain(false); //不須要原始數據 searchSourceBuilder.fetchSource(false); //不須要版本號 searchSourceBuilder.version(false); searchSourceBuilder.aggregation(aggregation); logger.info("查詢的語句:"+searchSourceBuilder.toString()); searchRequest.source(searchSourceBuilder); // 同步查詢 SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); return searchResponse; } protected static void agg(AggregationBuilder aggregation, String buk) throws IOException{ SearchResponse searchResponse = search(aggregation); if(RestStatus.OK.equals(searchResponse.status())) { // 獲取聚合結果 Aggregations aggregations = searchResponse.getAggregations(); if(buk.contains("avg")){ //取子聚合 Avg ba = aggregations.get(buk); logger.info(buk+":" + ba.getValue()); logger.info("------------------------------------"); }else if(buk.contains("max")){ //取子聚合 Max ba = aggregations.get(buk); logger.info(buk+":" + ba.getValue()); logger.info("------------------------------------"); }else if(buk.contains("min")){ //取子聚合 Min ba = aggregations.get(buk); logger.info(buk+":" + ba.getValue()); logger.info("------------------------------------"); }else if(buk.contains("sum")){ //取子聚合 Sum ba = aggregations.get(buk); logger.info(buk+":" + ba.getValue()); logger.info("------------------------------------"); }else if(buk.contains("top")){ //取子聚合TopHits TopHits ba = aggregations.get(buk); logger.info(buk+":" + ba.getHits().totalHits); logger.info("------------------------------------"); } } }
參考:
https://www.elastic.co/guide/en/elasticsearch/reference/6.5/search-aggregations.html
本篇文章的代碼已收錄在本人的java-study項目中,如有興趣,歡迎star、fork和issues。
項目地址:https://github.com/xuwujing/java-study
原創不易,若是感受不錯,但願給個推薦!您的支持是我寫做的最大動力! 版權聲明: 做者:虛無境 博客園出處:http://www.cnblogs.com/xuwujing CSDN出處:http://blog.csdn.net/qazwsxpcm 我的博客出處:http://www.panchengming.com