es筆記六之聚合操作之指標聚合

来源:https://www.cnblogs.com/hunterxiong/archive/2023/05/24/17429764.html
-Advertisement-
Play Games

> 本文首發於公眾號:Hunter後端 > 原文鏈接:[es筆記六之聚合操作之指標聚合](https://mp.weixin.qq.com/s/UyiZ2bzFxi7zCGmL1Xf3CQ) 聚合操作,在 es 中的聚合可以分為大概四種聚合: * bucketing(桶聚合) * mertic(指標 ...


本文首發於公眾號:Hunter後端
原文鏈接:es筆記六之聚合操作之指標聚合

聚合操作,在 es 中的聚合可以分為大概四種聚合:

  • bucketing(桶聚合)
  • mertic(指標聚合)
  • matrix(矩陣聚合)
  • pipeline(管道聚合)

bucket
類似於分類分組,按照某個 key 將符合條件的數據都放到該類別的組中

mertic
計算一組文檔的相關值,比如最大,最小值

matrix
根據多個 key 從文檔中提取值生成矩陣,這個操作不支持腳本(script)

pipeline
將其他聚合的結果再次聚合輸出

聚合是支持套娃(嵌套)操作的,你可以在聚合的結果上接著進行聚合操作,es 是不限制聚合的深度的。

本篇筆記目錄如下:

  1. 指標聚合的基本結構
  2. 平均值聚合
  3. 去重統計
  4. 聚合統計彙總
  5. 最大值、最小值聚合
  6. 百分位統計
  7. 百分位排名
  8. 字元串統計聚合
  9. sum 統計總和操作
  10. count 統計總數操作
  11. top hit 操作

1、指標聚合的基本結構

指標聚合操作的基本結構大致如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "aggregation_name": {
      "agg_name": {
        "field": "field_name"
      }
    }
  }
}

其中,aggregation_name 為聚合返回結果的名稱,由我們自己定義,agg_name 為聚合的參數,比如最大值最小值,平均值等,這個我們在下麵介紹。

指標聚合

指標聚合是從文檔中提取欄位值出來進行計算得出結果,比如最大最小平均值等。

接下來將詳細介紹各種指標聚合操作。

2、平均值聚合

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "avg_balance": {
      "avg": {
        "field": "balance"
      }
    }
  }
}

其中,最外層的 aggs 表示是聚合操作,avg_balance 是聚合的名稱,avg 則表示是平均值聚合,裡面的 field 表示聚合的欄位是 balance 欄位

在這裡,如果不添加 size=0,除了會返回我們的聚合結果,還會返回聚合的源數據。

這個操作我們返回的結果如下:

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1000,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "avg_balance" : {
      "value" : 25714.837
    }
  }
}

我們聚合的結果在 aggregations 這個 key 下。

腳本執行

腳本執行的方式如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "avg_balance": {
      "avg": {
        "script": {"source": "doc.balance.value"}
      }
    }
  }
}

對結果處理

假設,我們需要對這個平均值結果進行處理,比如我們計算出來的這個值是 2000,我們想要對這個值進行修正,比如乘以 1.2。

當然,這個乘的操作我們可以獲取數據之後在系統里進行操作,如果是直接在 es 的處理中,我們可以如下實現:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "avg_corrected_balance": {
      "avg": {
        "field": "balance", 
        "script": {
          "lang": "painless",
          "source": "_value * params.correction",
          "params": {"correction": 1.2}
          
        }
      }
    },
    "avg_balance": {
      "avg": {
        "script": {"source": "doc.balance.value"}
      }
    }
  }
}

在上面的語句中,我們新增了一個 params 欄位,定義了一個 correction 的值,然後返回的結果乘以了這個值。

在這裡,我額外加了一個 avg_balance,是直接用的平均值聚合結果,主要是用來對比這兩個結果。

缺失值補充

有一些情況,我們在導入數據的時候,可能某條數據的某個欄位是沒有值的,預設情況下他們是會被忽略的,不計入計算的,但是如果想要為其加一個預設值也是可以實現的,這裡我們用到 missing 這個參數來定義:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "avg_balance": {
      "avg": {
        "field": "balance",
        "missing": 0
      }
    }
  }
}

3、去重統計

是對某個欄位進行去重後統計總數,操作如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_count": {
      "cardinality": {
        "field": "age"
      }
    }
  }
}

需要註意的是,這個統計對於 text 欄位屬性是不生效的

4、聚合統計彙總

有一個聚合統計彙總的參數 stats,可以將一般的聚合值進行彙總後返回,比如總數,最大值,最小值等,使用如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_stats": {
      "stats": {
        "field": "age"
      }
    }
  }
}

可以看到返回的值如下:

{
 ...
 "aggregations" : {
    "age_stats" : {
      "count" : 1000,
      "min" : 20.0,
      "max" : 40.0,
      "avg" : 30.171,
      "sum" : 30171.0
    }
  }
}

如果還想獲得方差,標準差等數據,可以使用這個參數的擴展版 extended_stats,替換聚合的參數 stats 即可。

5、最大值、最小值聚合

最大值最小值的關鍵字是 max 和 min,使用示例如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "max_age": {
      "max": {"field": "age"}
    },
    "min_age": {
      "min": {"field": "age"}
    }
  }
}

使用腳本的方式來實現:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "max_age": {
      "max": {"script": {"source": "doc.age.value"}}
    }
  }
}

6、百分位統計

使用 es 進行百分位的統計,用到的關鍵字是 percentiles

使用示例如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_percentiles": {
      "percentiles": {
        "field": "age"
      }
    }
  }
}

會輸出 [1, 5, 25, 75, 95, 99] 的統計數:

{
  ...
  "aggregations" : {
    "age_percentiles" : {
      "values" : {
        "1.0" : 20.0,
        "5.0" : 21.0,
        "25.0" : 25.0,
        "50.0" : 30.8,
        "75.0" : 35.0,
        "95.0" : 39.0,
        "99.0" : 40.0
      }
    }
  }
}

我們也可以指定統計的百分位的數列表,比如我們只想知道 [75, 98, 99, 99.9] 的數據:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_percentiles": {
      "percentiles": {
        "field": "age",
        "percents": [75, 98, 99, 99.9]
      }
    }
  }
}

我們直接使用是返回的百分位-數據的格式,我們也可以使用 {'key': xx, 'value': xx} 來返回一個列表,加上一個參數 keyed=false 即可

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_percentiles": {
      "percentiles": {
        "field": "age",
        "keyed": false
      }
    }
  }
}

返回的結果示例如下:

    "age_percentiles" : {
      "values" : [
         ...
        {
          "key" : 75.0,
          "value" : 35.0
        },
        {
          "key" : 95.0,
          "value" : 39.0
        },
        {
          "key" : 99.0,
          "value" : 40.0
        }
      ]
    }
  }
}

7、百分位排名

這個是和前面的百分位統計相反的操作。

前面是根據百分位獲取該百分位值,這個參數的作用是根據數據獲取在系統中的百分位,使用示例如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_ranks": {
      "percentile_ranks": {
        "field": "age",
        "values": [
          30,
          35,
          40
        ]
      }
    }
  }
}

8、字元串統計聚合

對於字元串類型的數據,有一個專門的參數來獲取相應的聚合統計值,為 string_stats

對 lastname 欄位的統計示例如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "last_name_stats": {
      "string_stats": {"field": "lastname.keyword"}
    }
  }
}

需要註意,如果我們需要進行統計的欄位如果是 text 欄位,那麼就需要加上 .keyword 來進行統計,如果是欄位屬性是 keyword,就不需要這樣處理。

經過統計返回的數據如下:

  ... 
  "aggregations" : {
    "last_name_stats" : {
      "count" : 1000,
      "min_length" : 2,
      "max_length" : 11,
      "avg_length" : 6.122,
      "entropy" : 4.726472133462717
    }
  }
}

以上信息包括數據總數,lastname 欄位最長和最短長度,平均長度和熵值

9、sum 統計總和操作

比如我們需要對 bank 這個資料庫的 age 欄位進行 sum 的操作,可以如下操作:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_sum": {
      "sum": {"field": "age"}
    }
  }
}

在前面的每一個聚合操作里,都可以進行 query 的條件篩選,比如獲取 age=21 的數據的 sum 值:

GET /bank/_search
{
  "size": 0,
  "query": {"match": {"age": "21"}}, 
  "aggs": {
    "age_sum": {
      "sum": {"field": "age"}
    }
  }
}

10、count 統計總數操作

count 是統計總數,使用示例如下:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "age_count": {
      "value_count": {
        "field": "age"
      }
    }
  }
}

11、top hit 操作

top hit 操作是根據條件返回符合條件的前幾條數據,通過 size 控制返回的數量。

我們先來看下下麵的這個操作:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "top_ages": {
      "terms": {
        "field": "age",
        "size": 30
      }
    }
  }
}

這個操作其實就是一個桶聚合,它會在下一篇筆記中介紹,這裡我們直接用一下,它返回欄位為 age,以及它在文檔中的數量:

  ...
  "aggregations" : {
    "top_ages" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 31,
          "doc_count" : 61
        },
        {
          "key" : 39,
          "doc_count" : 60
        },
        {
          "key" : 26,
          "doc_count" : 59
        },
        ...

top_hits 的操作是在第一個 aggs 聚合操作條件下,進行再次聚合。

比如我們想要獲取各個 age 的數據中,按照 balance 欄位進行倒序排序的前三個,我們可以如下操作:

GET /bank/_search
{
  "size": 0,
  "aggs": {
    "top_ages": {
      "terms": {
        "field": "age",
        "size": 30
      },
      "aggs": {
        "top_balance_hits": {
          "top_hits": {
            "size": 3,
            "sort": [{"balance": {"order": "desc"}}]
          }
        }
      }
    }
  }
}

然後在第一次聚合返回的結果中,就會多一個 top_balance_hits 欄位,也就是我們在查詢操作中指定的,其下會有三條按照 balance 欄位倒序返回的數據:

  ...
  "aggregations" : {
    "top_ages" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : 31,
          "doc_count" : 61,
          "top_balance_hits" : {
            "hits" : {
              "total" : {
                "value" : 61,
                "relation" : "eq"
              },
              "max_score" : null,
              "hits" : [
                ...
              ]
        },
        {
          "key" : 39,
          "doc_count" : 60,
          ...
        },
        {
          "key" : 26,
          "doc_count" : 59,
          ...
        },
        ...

如果想獲取更多後端相關文章,可掃碼關註閱讀:
image


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在使用 using 等新語法時,在 VisualStudio 2019 會自動判斷框架版本,如在 net 45 就不會自動使用最新版本的語法,需要修改項目文件 在使用 C# 8.0 之前,請在官網 下載最新的 VisualStudio 2019 版本 如果在編譯時提示 “Using 聲明”在 C# ...
  • ​ 美國社會心理學家通過研究發現:當一個觀點對某人來說十分重要的時候,如果他能用這個觀點,使得一個“反對者”改變其原有意見,而和他的觀點一致,那麼他更傾向於喜歡那個“反對者”,而不是一個從始至終的同意者。這其實就是“改宗效應”。 對於那些正直的領導,一味拍馬屁,並不會換來他們的尊重,反而是那些偶然忤 ...
  • 最近接到一個新項目,需要在項目里添加一個後臺任務,定時去發郵件通知客戶;由於是一個比較小型的項目,不希望引入Quartz.Net、Hangfire等太重的框架,同時也沒持久化要;尋覓了一下發現ASP.NET Core本身帶有托管服務,可以執行定時任務。ASP.NET Core提供了IHostedSe ...
  • ### 一、什麼是NVM NVM是英文“Non-Volatile Memory”的縮寫,中文翻譯為“非易失性存儲器”。它是指一種能夠在斷電情況下依舊保留數據的存儲器件。NVM用於存儲一些不需要頻繁更改的數據,例如汽車電子控制單元(ECU)中的程式代碼、校準數據、配置參數以及歷史故障碼等。 ### 二 ...
  • 目錄 一、pxe概念 二、pxe相關服務 三、pxe裝機流程 四、pxe四大文件 五、無人值守 六、實驗 自動裝機 一、pxe概念 概念:PXE(預啟動執行環境)是由Intel公司開發的網路引導技術,工作在Client/Server模式,允許客戶機通過網路從遠程伺服器下載引導鏡像,並載入安裝文件或者 ...
  • 官網下載 Java 您可以從官方網站下載 Java 的最新穩定版本。 官網地址:https://www.oracle.com/technetwork/java/javase/overview/index.html 安裝 Java 有些電腦可能已經安裝了Java。 要檢查Windows PC上是否安裝 ...
  • 小白一枚,今天來給大家分享一下如何將自己編寫的桌面應用程式進行打包,便於在其他的電腦上進行安裝使用。如有錯誤之處請大家指正,謝謝!好了,廢話不多說開乾。 這裡簡要的介紹一下使用QtCreator編寫的應用程式的打包。 1. 將Debug模式切換稱為ewlease模式進行編譯,編譯後沒有任何錯誤即可( ...
  • 開發板:NanoPC-T4開發板eMMC:16GBLPDDR3:4GB顯示屏:15.6 HDMI介面顯示屏u-boot :2023.04 在前面我們已經介紹了編譯Rockchip官方提供的uboot源碼,並下載到開發板中進行測試運行。這一節我們嘗試下載最新的uboot版本試試,當前最新版本為2023 ...
一周排行
    -Advertisement-
    Play Games
  • 概述:在C#中,++i和i++都是自增運算符,其中++i先增加值再返回,而i++先返回值再增加。應用場景根據需求選擇,首碼適合先增後用,尾碼適合先用後增。詳細示例提供清晰的代碼演示這兩者的操作時機和實際應用。 在C#中,++i 和 i++ 都是自增運算符,但它們在操作上有細微的差異,主要體現在操作的 ...
  • 上次發佈了:Taurus.MVC 性能壓力測試(ap 壓測 和 linux 下wrk 壓測):.NET Core 版本,今天計劃準備壓測一下 .NET 版本,來測試並記錄一下 Taurus.MVC 框架在 .NET 版本的性能,以便後續持續優化改進。 為了方便對比,本文章的電腦環境和測試思路,儘量和... ...
  • .NET WebAPI作為一種構建RESTful服務的強大工具,為開發者提供了便捷的方式來定義、處理HTTP請求並返迴響應。在設計API介面時,正確地接收和解析客戶端發送的數據至關重要。.NET WebAPI提供了一系列特性,如[FromRoute]、[FromQuery]和[FromBody],用 ...
  • 原因:我之所以想做這個項目,是因為在之前查找關於C#/WPF相關資料時,我發現講解圖像濾鏡的資源非常稀缺。此外,我註意到許多現有的開源庫主要基於CPU進行圖像渲染。這種方式在處理大量圖像時,會導致CPU的渲染負擔過重。因此,我將在下文中介紹如何通過GPU渲染來有效實現圖像的各種濾鏡效果。 生成的效果 ...
  • 引言 上一章我們介紹了在xUnit單元測試中用xUnit.DependencyInject來使用依賴註入,上一章我們的Sample.Repository倉儲層有一個批量註入的介面沒有做單元測試,今天用這個示例來演示一下如何用Bogus創建模擬數據 ,和 EFCore 的種子數據生成 Bogus 的優 ...
  • 一、前言 在自己的項目中,涉及到實時心率曲線的繪製,項目上的曲線繪製,一般很難找到能直接用的第三方庫,而且有些還是定製化的功能,所以還是自己繪製比較方便。很多人一聽到自己畫就害怕,感覺很難,今天就分享一個完整的實時心率數據繪製心率曲線圖的例子;之前的博客也分享給DrawingVisual繪製曲線的方 ...
  • 如果你在自定義的 Main 方法中直接使用 App 類並啟動應用程式,但發現 App.xaml 中定義的資源沒有被正確載入,那麼問題可能在於如何正確配置 App.xaml 與你的 App 類的交互。 確保 App.xaml 文件中的 x:Class 屬性正確指向你的 App 類。這樣,當你創建 Ap ...
  • 一:背景 1. 講故事 上個月有個朋友在微信上找到我,說他們的軟體在客戶那邊隔幾天就要崩潰一次,一直都沒有找到原因,讓我幫忙看下怎麼回事,確實工控類的軟體環境複雜難搞,朋友手上有一個崩潰的dump,剛好丟給我來分析一下。 二:WinDbg分析 1. 程式為什麼會崩潰 windbg 有一個厲害之處在於 ...
  • 前言 .NET生態中有許多依賴註入容器。在大多數情況下,微軟提供的內置容器在易用性和性能方面都非常優秀。外加ASP.NET Core預設使用內置容器,使用很方便。 但是筆者在使用中一直有一個頭疼的問題:服務工廠無法提供請求的服務類型相關的信息。這在一般情況下並沒有影響,但是內置容器支持註冊開放泛型服 ...
  • 一、前言 在項目開發過程中,DataGrid是經常使用到的一個數據展示控制項,而通常表格的最後一列是作為操作列存在,比如會有編輯、刪除等功能按鈕。但WPF的原始DataGrid中,預設只支持固定左側列,這跟大家習慣性操作列放最後不符,今天就來介紹一種簡單的方式實現固定右側列。(這裡的實現方式參考的大佬 ...