序文
ES 統計分析の概念
ES の集計クエリは、SQL SUM/AVG/COUNT/GROUP BY グループ クエリと同様、主に統計分析シナリオで使用されます。
以下では、最初に ES 集約クエリの中心となるプロセスと中心となる概念を紹介します。
1. ES集計クエリ処理
ES 集計クエリは SQL の GROUP by に似ており、一般的な統計分析は主に 2 つのステップに分かれています。
グループ分けグループ内での集計
まず、問い合わせたデータに対して一巡のグループ分けを行い、例えば新入生入学時には全学生を専攻ごとにクラス分けするなどのグループ分け条件を設定します。グループの生徒たち。
グループ内の集計とは、グループ内のデータの統計を作成することです。たとえば、合計を計算したり、平均を計算したりすることです。上記の例に従って、学生を専攻に従ってクラスに分け、その合計数を計算します。この統計は、各クラスの生徒数の合計をグループ内で集計したものです。
ヒント: グループ化は、SQL group by ステートメントによって設定される条件に似ており、グループ内の集計は、select で記述された avg、sum、および count 統計関数です。SQL ステートメントに精通している人は、sum および count 統計関数が関数であることを知っています。関数は必ずしも group by ステートメントと連携する必要はありません。統計関数を単独で使用することは、すべてのデータを 1 つのグループに分割し、すべてのデータを直接カウントすることと同じです。
2. 中心となる概念
上記の集計クエリ プロセスを通じて、ES 集計の中心となる概念は次のようになります。これは理解しやすいものです。
2.1. バケット
特定の基準を満たすドキュメントのコレクションはバケットと呼ばれます。
バケットはデータのグループの集合であり、データをグループ化した後、データのグループが取得されます。これがバケットです。
ヒント: バケットはグループと同等です。バケット化とグループ化は同じ意味です。ES ではバケットを使用して、同じ特性を持つデータのセットを表します。
ES でのバケット集計は、最初にデータをグループ化することを指します。ES は、複数のグループ化条件をサポートしています。たとえば、フィールドごとにグループ化する SQL のようなグループ化をサポートしています。もちろん、ES は SQL よりも強力で、さまざまな統計ニーズを満たすために、より多くのグループ化条件をサポートしています。 。
2.2. 指標
インデックスとは、ドキュメントの統計計算方法を指し、インデックス集計とも呼ばれます。
バケット内集計とは、最初にデータをグループ化し (バケット化)、次に各バケット内のデータに対してインジケーター集計を実行することを指します。
端的に言えば、データを一連のバケットに集約し、データをバケットに分割した後、上記の計算指標に基づいてバケット内のデータをカウントします。
一般的に使用される指標には、SUM、COUNT、MAX およびその他の統計関数が含まれます。
SQL 統計ステートメントを使用してバケットとインジケーターを理解します。
SELECT COUNT(*)
FROM order
GROUP BY shop_id
説明:
COUNT( ) は、統計インジケーターとも呼ばれるインジケーターと同等です。
GROUP BY shop_id はバケット化の条件に相当し、グループ化条件とも言えますが、同一の shop_id のデータを全て 1 つのバケットに分割します。
この SQL 文の機能は各店舗の注文数をカウントすることなので、SQL 統計の最初のステップは、同じ shop_id (店舗 ID) を持つデータを group by の条件に従ってグループ (バケット) に分割することです。 shop_id、そして一連のデータは count( ) 統計関数 (インジケーター) を使用して合計を計算し、最終的に各店舗の合計注文数を取得します。ES も同様のプロセスです。
3. ES 集約クエリ構文
まず、ES 集計クエリの基本的な文法構造を一般的に理解することができます。
{
"aggregations" : {
"<aggregation_name>" : {
"<aggregation_type>" : {
<aggregation_body>
}
[,"aggregations" : {
[<sub_aggregation>]+ } ]? // 嵌套聚合查询,支持多层嵌套
}
[,"<aggregation_name_2>" : {
... } ]* // 多个聚合查询,每个聚合查询取不同的名字
}
}
説明:
aggregations - 集計クエリ ステートメントを表します。 aggs <aggregation_name> と省略できます。
ES は一度に複数の統計分析クエリをサポートしているため、任意に名前を付けることができる集計計算の名前を表します。この名前は、後で必要な計算結果をクエリ結果で見つけるために使用します。
<aggregation_type> - データのカウント方法を表す集計タイプです。集計タイプには、バケット集計とインジケーター集計の 2 つの主なタイプがあります。これら 2 つのタイプの集計には、複数の集計タイプが含まれます。例: インジケーター集計: sum、avg 、バケット集計: 用語、日付ヒストグラムなど。
<aggregation_body> - 集計タイプのパラメータ 集計タイプが異なれば、パラメータも異なります。
aggregation_name_2 - 他の集計計算の名前を表します。これは、複数のタイプの統計を一度に実行できることを意味します。
単純な集計クエリの例を見てみましょう。
各車の販売注文を格納する注文インデックスがあり、これには車の色フィールドの色が含まれていると仮定します。
GET /order/_search
{
"size" : 0, // 设置size=0的意思就是,仅返回聚合查询结果,不返回普通query查询结果。
"aggs" : {
// 聚合查询语句的简写
"popular_colors" : {
// 给聚合查询取个名字,叫popular_colors
"terms" : {
// 聚合类型为,terms,terms是桶聚合的一种,类似SQL的group by的作用,根据字段分组,相同字段值的文档分为一组。
"field" : "color" // terms聚合类型的参数,这里需要设置分组的字段为color,根据color分组
}
}
}
}
上記ではバケット集計という用語が使用されていますが、インデックス集計関数は明示的に指定されていません。デフォルトでは、Value Count 集計インデックスを使用してドキュメントの総数をカウントします。全体の統計とは、各車の色の販売をカウントすることを意味します。
同等の SQL は次のとおりです。
select count(color) from order group by color
{
...
"hits": {
// 因为size=0,所以query查询结果为空
"hits": []
},
"aggregations": {
// 聚合查询结果
"popular_colors": {
// 这个就是popular_colors聚合查询的结果,这就是为什么需要给聚合查询取个名字的原因,如果有多个聚合查询,可以通过名字查找结果
"buckets": [ // 因为是桶聚合,所以看到返回一个buckets数组,代表分组的统计情况,下面可以看到每一种颜色的销量情况
{
"key": "red",
"doc_count": 4 // 红色的汽车销量为4
},
{
"key": "blue",
"doc_count": 2
},
{
"key": "green",
"doc_count": 2
}
]
}
}
}
4. インデックスの集計
ES インジケーター集計は SQL に似た統計関数であり、単独で使用することも、バケット集計と組み合わせて使用することもできます。
一般的に使用される統計関数は次のとおりです。
Value Count - SQL に似た count 関数、合計
カーディナリティをカウントします SQL に似た count (DISTINCT フィールド)、非反復データの総数をカウントします
Avg - 平均を計算します
Sum - 合計
Max -最大値を計算する
Min - 最小値を見つける
以下では、Elasticsearch で一般的に使用される統計関数の使用法について説明します。
4.1、値のカウント
値の集計。SQL の count 関数と同様に、主にドキュメントの総数をカウントするために使用されます。
例:
GET /sales/_search?size=0
{
"aggs": {
"types_count": {
// 聚合查询的名字,随便取个名字
"value_count": {
// 聚合类型为:value_count
"field": "type" // 计算type这个字段值的总数
}
}
}
}
等价SQL:
select count(type) from sales
返される結果:
{
...
"aggregations": {
"types_count": {
// 聚合查询的名字
"value": 7 // 统计结果
}
}
}
4.2、カーディナリティ
カーディナリティ集計は、ドキュメントの総数をカウントするためにも使用されます。値カウントとの違いは、SQL でのカウント (DISTINCT フィールド) の使用法と同様に、カーディナリティ集計では重複が排除され、重複した値はカウントされないことです。
例:
POST /sales/_search?size=0
{
"aggs" : {
"type_count" : {
// 聚合查询的名字,随便取一个
"cardinality" : {
// 聚合查询类型为:cardinality
"field" : "type" // 根据type这个字段统计文档总数
}
}
}
}
同等の SQL:
select count(DISTINCT type) from sales
{
...
"aggregations" : {
"type_count" : {
// 聚合查询的名字
"value" : 3 // 统计结果
}
}
}
ヒント: 前述したように、カーディナリティ集計の機能は SQL のカウント (DISTINCT フィールド) の使用と同等ですが、SQL のカウント統計の結果は精度を失うことなく正確な統計であるため、あまり正確ではありませんが、カーディナリティの合計数はES のカーディナリティ集計統計値は近似値であり、ある程度の誤差が生じますが、大量のデータの総数を正確に統計することは非常にパフォーマンスを消費するため、これはパフォーマンスを目的としていますが、多くのビジネス シナリオでは必要ありません。正確な結果、おおよその値のみ。例: 統計ウェブサイト 1 日のアクセス数に多少の誤差があっても問題ありません。
4.3、平均
平均的な
例:
POST /exams/_search?size=0
{
"aggs": {
"avg_grade": {
// 聚合查询名字,随便取一个名字
"avg": {
// 聚合查询类型为: avg
"field": "grade" // 统计grade字段值的平均值
}
}
}
}
返される結果:
{
...
"aggregations": {
"avg_grade": {
// 聚合查询名字
"value": 75.0 // 统计结果
}
}
}
4.4、合計
合計の計算
例:
POST /sales/_search?size=0
{
"aggs": {
"hat_prices": {
// 聚合查询名字,随便取一个名字
"sum": {
// 聚合类型为:sum
"field": "price" // 计算price字段值的总和
}
}
}
}
返される結果:
{
...
"aggregations": {
"hat_prices": {
// 聚合查询名字
"value": 450.0 // 统计结果
}
}
}
4.5.最大
最大値を見つける
例:
POST /sales/_search?size=0
{
"aggs": {
"max_price": {
// 聚合查询名字,随便取一个名字
"max": {
// 聚合类型为:max
"field": "price" // 求price字段的最大值
}
}
}
}
返される結果:
{
...
"aggregations": {
"max_price": {
// 聚合查询名字
"value": 200.0 // 最大值
}
}
}
4.6.分
最小値を見つける
例:
POST /sales/_search?size=0
{
"aggs": {
"min_price": {
// 聚合查询名字,随便取一个
"min": {
// 聚合类型为: min
"field": "price" // 求price字段值的最小值
}
}
}
}
戻る:
{
...
"aggregations": {
"min_price": {
// 聚合查询名字
"value": 10.0 // 最小值
}
}
}
4.7. 包括的な例
前の例では、集計インデックスのみを使用する場合のみを紹介しましたが、実際のアプリケーションでは、最初にインデックス内のデータがクエリ クエリによって検索され、その後、クエリ クエリの結果に対して統計分析が実行されることがよくあります。
例:
GET /sales/_search
{
"size": 0, // size = 0,代表不想返回query查询结果,只要统计结果
"query": {
// 设置query查询条件,后面的aggs统计,仅对query查询结果进行统计
"constant_score": {
"filter": {
"match": {
"type": "hat"
}
}
}
},
"aggs": {
// 统计query查询结果, 默认情况如果不写query语句,则代表统计所有数据
"hat_prices": {
// 聚合查询名字,计算price总和
"sum": {
"field": "price"
}
},
"min_price": {
// 聚合查询名字,计算price最小值
"min": {
"field": "price"
}
},
"max_price": {
// 聚合查询名字,计算price最大值
"max": {
"field": "price"
}
}
}
}
戻る:
{
...
"aggregations": {
"hat_prices": {
// 求和
"value": 450.0
},
"min_price": {
// 最小值
"value": 10.0
},
"max_price": {
// 最大值
"value": 200.0
}
}
}
5. グループ集計クエリ
Elasticsearch バケット集計の目的はデータをグループ化することであり、まず指定した条件に従ってデータを複数のグループに分割し、グループごとに統計を作成します。グループの概念はバケットに相当し、ES ではバケットという用語が一律に使用されます。
ES バケット集計の機能は SQL のグループ化と同じです。違いは、ES がより強力なデータ グループ化機能をサポートしていることです。SQL はフィールドの一意の値によってのみグループ化できます。グループの数は、グループの数と同じです。フィールドの一意の値。例: ショップ ID ごとにグループ化し、重複するショップ ID を削除した後、ショップの数と同じ数のグループが存在します。
ES で一般的に使用されるバケット集計は次のとおりです。
用語集計 - SQL のグループ化に似ており、フィールドの一意の値に従ってグループ化します。
ヒストグラム集計 - 数値間隔に従ってグループ化します。たとえば、価格は 100 間隔、0、100 でグループ化されます。 、200、300 など。
日付ヒストグラム集計 - 時間間隔ごとにグループ化します。たとえば、月、日、時間ごとにグループ化します。
範囲集計 - 値の範囲ごとにグループ化します。たとえば、0 ~ 150 グループ、150 ~ 200 グループ、200 ~ 500グループ。
ヒント: バケット集計は通常、単独で使用されるのではなく、インデックス集計と一緒に使用されます。データをグループ化した後、バケット内のデータをカウントする必要があります。インデックス集計が ES で明示的に指定されていない場合は、Value Count インデックス集計が使用されますデフォルトでは、バケット内のドキュメントの総数をカウントします。
5.1、用語の集約
用語集計の機能は SQL の group by と同じで、フィールドの一意の値に従ってデータがグループ化 (バケット化) され、フィールド値が等しいドキュメントは同じバケットにグループ化されます。
例:
GET /order/_search?size=0
{
"aggs": {
"shop": {
// 聚合查询的名字,随便取个名字
"terms": {
// 聚合类型为: terms
"field": "shop_id" // 根据shop_id字段值,分桶
}
}
}
}
等价SQL:
select shop_id, count(*) from order group by shop_id
返される結果:
{
...
"aggregations" : {
"shop" : {
// 聚合查询名字
"buckets" : [ // 桶聚合结果,下面返回各个桶的聚合结果
{
"key" : "1", // key分桶的标识,在terms聚合中,代表的就是分桶的字段值
"doc_count" : 6 // 默认的指标聚合是统计桶内文档总数
},
{
"key" : "5",
"doc_count" : 3
},
{
"key" : "9",
"doc_count" : 2
}
]
}
}
}
5.2、ヒストグラムの集計
ヒストグラム (ヒストグラム) 集計は、主に数値間隔に従ってグループ化され、通常は棒グラフ レポートを描画するために使用されるヒストグラム集計バケット統計結果を使用します。
例:
POST /sales/_search?size=0
{
"aggs" : {
"prices" : {
// 聚合查询名字,随便取一个
"histogram" : {
// 聚合类型为:histogram
"field" : "price", // 根据price字段分桶
"interval" : 50 // 分桶的间隔为50,意思就是price字段值按50间隔分组
}
}
}
}
返される結果:
{
...
"aggregations": {
"prices" : {
// 聚合查询名字
"buckets": [ // 分桶结果
{
"key": 0.0, // 桶的标识,histogram分桶,这里通常是分组的间隔值
"doc_count": 1 // 默认按Value Count指标聚合,统计桶内文档总数
},
{
"key": 50.0,
"doc_count": 1
},
{
"key": 100.0,
"doc_count": 0
},
{
"key": 150.0,
"doc_count": 2
}
]
}
}
}
5.3、日付ヒストグラムの集計
ヒストグラム集計と同様に、日付ヒストグラムは時間タイプのフィールドを非常に適切に処理でき、主に時間と日付に基づくバケット化シナリオに使用される点が異なります。
例:
POST /sales/_search?size=0
{
"aggs" : {
"sales_over_time" : {
// 聚合查询名字,随便取一个
"date_histogram" : {
// 聚合类型为: date_histogram
"field" : "date", // 根据date字段分组
"calendar_interval" : "month", // 分组间隔:month代表每月、支持minute(每分钟)、hour(每小时)、day(每天)、week(每周)、year(每年)
"format" : "yyyy-MM-dd" // 设置返回结果中桶key的时间格式
}
}
}
}
返される結果:
{
...
"aggregations": {
"sales_over_time": {
// 聚合查询名字
"buckets": [ // 桶聚合结果
{
"key_as_string": "2015-01-01", // 每个桶key的字符串标识,格式由format指定
"key": 1420070400000, // key的具体字段值
"doc_count": 3 // 默认按Value Count指标聚合,统计桶内文档总数
},
{
"key_as_string": "2015-02-01",
"key": 1422748800000,
"doc_count": 2
},
{
"key_as_string": "2015-03-01",
"key": 1425168000000,
"doc_count": 2
}
]
}
}
}
5.4、範囲集計
範囲集計、値範囲によるバケット化。
例:
GET /_search
{
"aggs" : {
"price_ranges" : {
// 聚合查询名字,随便取一个
"range" : {
// 聚合类型为: range
"field" : "price", // 根据price字段分桶
"ranges" : [ // 范围配置
{
"to" : 100.0 }, // 意思就是 price <= 100的文档归类到一个桶
{
"from" : 100.0, "to" : 200.0 }, // price>100 and price<200的文档归类到一个桶
{
"from" : 200.0 } // price>200的文档归类到一个桶
]
}
}
}
}
返される結果:
{
...
"aggregations": {
"price_ranges" : {
// 聚合查询名字
"buckets": [ // 桶聚合结果
{
"key": "*-100.0", // key可以表达分桶的范围
"to": 100.0, // 结束值
"doc_count": 2 // 默认按Value Count指标聚合,统计桶内文档总数
},
{
"key": "100.0-200.0",
"from": 100.0, // 起始值
"to": 200.0, // 结束值
"doc_count": 2
},
{
"key": "200.0-*",
"from": 200.0,
"doc_count": 3
}
]
}
}
}
よく観察すると、範囲バケットのデフォルトのキー値はあまり使いやすいものではないことがわかります。特に開発中、キーがどのようなものであるかがわからないと、対処するのが面倒です。意味のある名前を割り当てることができます。各バケットに。
例:
GET /_search
{
"aggs" : {
"price_ranges" : {
"range" : {
"field" : "price",
"keyed" : true,
"ranges" : [
// 通过key参数,配置每一个分桶的名字
{
"key" : "cheap", "to" : 100 },
{
"key" : "average", "from" : 100, "to" : 200 },
{
"key" : "expensive", "from" : 200 }
]
}
}
}
}
5.5. 包括的な例
前の例では、aggs 集計ステートメントが単独で使用されています。これは、すべてのドキュメントが直接カウントされることを意味します。実際のアプリケーションでは、クエリ ステートメントと連携して、最初にターゲット ドキュメントを検索してから、aggs 集計ステートメントを使用する必要があることがよくあります。検索結果に対して統計分析を実行するステートメント。
例:
GET /cars/_search
{
"size": 0, // size=0代表不需要返回query查询结果,仅仅返回aggs统计结果
"query" : {
// 设置查询语句,先赛选文档
"match" : {
"make" : "ford"
}
},
"aggs" : {
// 然后对query搜索的结果,进行统计
"colors" : {
// 聚合查询名字
"terms" : {
// 聚合类型为:terms 先分桶
"field" : "color"
},
"aggs": {
// 通过嵌套聚合查询,设置桶内指标聚合条件
"avg_price": {
// 聚合查询名字
"avg": {
// 聚合类型为: avg指标聚合
"field": "price" // 根据price字段计算平均值
}
},
"sum_price": {
// 聚合查询名字
"sum": {
// 聚合类型为: sum指标聚合
"field": "price" // 根据price字段求和
}
}
}
}
}
}
集計クエリは、複数レベルのネストをサポートします。
6. 集計後のソート
term、histogram、date_histogram などのバケット集計では、複数のバケットが動的に生成されます。生成されたバケットが多すぎる場合、これらのバケットの並べ替え順序をどのように決定し、返されるバケットの数を制限すればよいでしょうか。
6.1. マルチバケットのソート
デフォルトでは、ES は doc_count ドキュメントの合計数に従って降順に並べ替えます。
ES バケット集計では、
組み込みの並べ替え
とメトリックによる並べ替えの2 つの並べ替え方法がサポートされています。
組み込みの並べ替え、組み込みの並べ替えパラメーター:
_count - ドキュメントの数で並べ替えます。用語、ヒストグラム、date_histogram_term に有効
- 用語の文字列値によってアルファベット順に並べ替えます。_key は用語内でのみ使用します
- 各バケットのキー値で並べ替えます。ヒストグラムと date_histogram にのみ有効です
。 例:
GET /cars/_search
{
"size" : 0,
"aggs" : {
"colors" : {
// 聚合查询名字,随便取一个
"terms" : {
// 聚合类型为: terms
"field" : "color",
"order": {
// 设置排序参数
"_count" : "asc" // 根据_count排序,asc升序,desc降序
}
}
}
}
}
6.2. メジャーによるソート
通常、バケット集計とバケット化の後、バケット内の複数のディメンションのインジケーターを集計するため、バケット内のインジケーター集計の結果に従って並べ替えることもできます。
例:
GET
GET /cars/_search
{
"size" : 0,
"aggs" : {
"colors" : {
// 聚合查询名字
"terms" : {
// 聚合类型: terms,先分桶
"field" : "color", // 分桶字段为color
"order": {
// 设置排序参数
"avg_price" : "asc" // 根据avg_price指标聚合结果,升序排序。
}
},
"aggs": {
// 嵌套聚合查询,设置桶内聚合指标
"avg_price": {
// 聚合查询名字,前面排序引用的就是这个名字
"avg": {
"field": "price"} // 计算price字段平均值
}
}
}
}
}
6.3. 返されるバケットの数を制限する
バケットが多すぎる場合は、バケット集約にサイズ パラメーターを追加することで、返されるバケットの数を制限できます。
例:
GET /_search
{
"aggs" : {
"products" : {
// 聚合查询名字
"terms" : {
// 聚合类型为: terms
"field" : "product", // 根据product字段分桶
"size" : 5 // 限制最多返回5个桶
}
}
}
}