集計操作を実行して、最小値、最大値、合計、平均値、行数と個別行数のカウント、パーセンタイル統計を取得できます。また、集計操作を実行して、フィールド値、範囲、地理的位置、フィルター、ヒストグラム、または日付ヒストグラム別に結果をグループ化し、ネストされたクエリを実行することもできます。複雑なクエリに対して複数の集計操作を実行できます。
手順
次の図は、完全な集計手順を示しています。
サーバーは、クエリ条件を満たすデータをクエリし、リクエストに基づいてデータの集計を実行します。そのため、集計を必要とするリクエストは、集計を必要としないリクエストよりも複雑です。
背景情報
次の表は、集計方法について説明しています。
方法 | 説明 |
最小値 | フィールドの最小値を返すために使用できる集計方法です。この方法は、SQLのMIN関数と同様に使用できます。 |
最大値 | フィールドの最大値を返すために使用できる集計方法です。この方法は、SQLのMAX関数と同様に使用できます。 |
合計 | 数値フィールドのすべての値の合計を返すために使用できる集計方法です。この方法は、SQLのSUM関数と同様に使用できます。 |
平均値 | 数値フィールドのすべての値の平均を返すために使用できる集計方法です。この方法は、SQLのAVG関数と同様に使用できます。 |
カウント | フィールドの値の総数または検索インデックスの行の総数を返すために使用できる集計方法です。この方法は、SQLのCOUNT関数と同様に使用できます。 |
個別カウント | フィールドの個別値の数を返すために使用できる集計方法です。この方法は、SQLのCOUNT(DISTINCT)関数と同様に使用できます。 |
パーセンタイル統計 | パーセンタイル値は、データセット内の値の相対的な位置を示します。たとえば、システムの日常的なO&M中に各リクエストの応答時間に関する統計を収集する場合、p25、p50、p90、p99などのパーセンタイルを使用して応答時間の分布を分析する必要があります。 |
フィールド値によるグループ化 | フィールド値に基づいてクエリ結果をグループ化するために使用できる集計方法です。同じ値は一緒にグループ化されます。同一の値は一緒にグループ化されます。各グループの同一の値と各グループの同一の値の数が返されます。 説明 グループに過度に多数の値が含まれている場合、計算された数値は実際の数値と異なる場合があります。 |
複数フィールドによるグループ化 | 複数のフィールドに基づいてクエリ結果をグループ化するために使用できる集計方法です。トークンを使用してページングを実行できます。 |
範囲によるグループ化 | フィールドの値の範囲に基づいてクエリ結果をグループ化するために使用できる集計方法です。指定された範囲内のフィールド値は一緒にグループ化されます。各範囲の値の数が返されます。 |
地理的位置によるグループ化 | 地理的位置から中心点までの距離に基づいてクエリ結果をグループ化するために使用できる集計方法です。指定された範囲内の距離のクエリ結果は一緒にグループ化されます。各範囲の項目数が返されます。 |
フィルターによるグループ化 | クエリ結果をフィルタリングし、各フィルターに基づいてグループ化して、一致する結果の数を取得するために使用できる集計方法です。結果は、フィルターが指定された順序で返されます。 |
ヒストグラムによるクエリ | この集計方法は、特定のデータ間隔に基づいてクエリ結果をグループ化するために使用できます。同じ範囲内のフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。 |
日付ヒストグラムによるクエリ | 特定の日付間隔に基づいてクエリ結果をグループ化するために使用できる集計方法です。同じ範囲内のフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。 |
各グループの集計操作の結果から取得された行のクエリ | クエリ結果をグループ化した後、各グループの行をクエリできます。この方法は、MySQLのANY_VALUE(field)と同様に使用できます。 |
ネスト | GroupByはネストをサポートしています。GroupByを使用してサブ集計操作を実行できます。 |
複数集計 | 複数の集計操作を実行できます。 説明 複数の複雑な集計操作を同時に実行すると、長時間を要する場合があります。 |
API操作
Search 操作を呼び出して、集計機能を使用できます。
前提条件
Tablestoreコンソール、CLI、またはSDKを使用して集計操作を実行できます。集計操作を実行する前に、次の準備が整っていることを確認してください。
TablestoreコンソールまたはCLIを使用する場合、すべての集計機能にアクセスできない場合があります。実際に利用可能な集計機能が優先されます。
Tablestoreで操作を実行する権限を持つAlibaba CloudアカウントまたはRAMユーザーを持っていること。RAMユーザーにTablestore操作権限を付与する方法については、RAMポリシーを使用してRAMユーザーに権限を付与するを参照してください。
Tablestore SDKまたはTablestore CLIを使用してクエリを実行する場合、Alibaba CloudアカウントまたはRAMユーザーのAccessKeyペアが作成されます。詳細については、AccessKeyペアを作成するを参照してください。
データテーブルが作成されていること。詳細については、テーブルの操作を参照してください。
データテーブルの検索インデックスが作成されていること。詳細については、検索インデックスを作成するを参照してください。
Tablestore SDKを使用してクエリを実行する場合、OTSClientインスタンスが初期化されていること。詳細については、OTSClientインスタンスを初期化するを参照してください。
Tablestore CLIを使用してクエリを実行する場合、Tablestore CLIがダウンロードされて起動され、アクセスするインスタンスとデータテーブルに関する情報が設定されていること。詳細については、Tablestore CLIをダウンロードする、Tablestore CLIを起動し、アクセス情報を設定する、およびデータテーブルの操作を参照してください。
Tablestoreコンソールの使用
インデックスタブに移動します。
Tablestoreコンソールにログオンします。
上部のナビゲーションバーで、リソースグループとリージョンを選択します。
概要ページで、管理するインスタンスの名前をクリックするか、インスタンスのアクション列のインスタンスの管理をクリックします。
インスタンスの詳細タブのテーブルタブで、データテーブルの名前をクリックするか、データテーブルのアクション列のインデックスをクリックします。
インデックスタブで、データのクエリに使用する検索インデックスを見つけ、アクション列のデータの管理をクリックします。
検索ダイアログボックスで、クエリ条件を指定します。
デフォルトでは、システムはすべての属性列を返します。特定の属性列を返すには、すべての列をオフにして、返す属性列を指定します。複数の属性列はコンマ(,)で区切ります。
説明デフォルトでは、システムはデータテーブルのすべての主キー列を返します。
ビジネス要件に基づいて、And、Or、またはNot論理演算子を選択します。
And論理演算子を選択すると、クエリ条件を満たすデータが返されます。Or演算子を選択して単一のクエリ条件を指定すると、そのクエリ条件を満たすデータが返されます。Or論理演算子を選択して複数のクエリ条件を指定すると、いずれかのクエリ条件を満たすデータが返されます。Not論理演算子を選択すると、クエリ条件を満たさないデータが返されます。
インデックスフィールドを選択し、追加をクリックします。次に、クエリタイプと値パラメータを設定します。
この手順を繰り返して、複数のインデックスフィールドのクエリ条件を追加できます。
デフォルトでは、並べ替え機能は無効になっています。特定のフィールドに基づいてクエリ結果を並べ替える場合は、並べ替えをオンにして、クエリ結果を並べ替えるフィールドと並べ替え順序を指定します。
デフォルトでは、統計の収集はオフになっています。特定のフィールドの統計を収集する場合は、統計の収集をオンにして、ビジネス要件に基づいて次のパラメータを設定します。フィールド名、統計タイプ、項目、デフォルト。
統計の収集をオンにした後、複数のフィールドを同時に追加できます。統計タイプパラメータには、最小、最大、合計、平均、カウント、または個別カウントの値を設定できます。デフォルトパラメータは、インデックスフィールドが行に存在しない場合に有効になります。
OKをクリックします。
クエリ条件を満たすデータと統計結果は、インデックスタブに表示されます。
Tablestore CLIの使用
Tablestore CLIでsearch
コマンドを実行して、集計リクエストを開始できます。Tablestore CLIを使用する場合、次の集計操作がサポートされています。最小値の取得、最大値の取得、合計の取得、平均値の取得、および行数のカウント。詳細については、検索インデックスを参照してください。
次の
search
コマンドを実行して、データテーブル内のデータをクエリおよび分析し、すべてのインデックス付き列を返します。search -n search_index --return_all_indexed
プロンプトが表示されたら、クエリ条件を入力します。
次のサンプルコードは、gid列の値が10未満または77と完全に一致する行をクエリし、gid列の値を平均化する例を示しています。
{ "Offset": -1, "Limit": 10, "Collapse": null, "Sort": null, "GetTotalCount": true, "Token": null, "Query": { "Name": "BoolQuery", "Query": { "MinimumShouldMatch": null, "MustQueries": null, "MustNotQueries": null, "FilterQueries": null, "ShouldQueries": [{ "Name": "RangeQuery", "Query": { "FieldName": "gid", "From": null, "To": 10, "IncludeLower": false, "IncludeUpper": false } }, { "Name": "TermQuery", "Query": { "FieldName": "gid", "Term": 77 } }] } }, "Aggregations": [{ "Name": "avg", "Aggregation": { "AggName": "agg1", "Field": "gid", "MissingValue": null } }] }
Tablestore SDKの使用
集計操作は、次のTablestore SDKでサポートされています。Tablestore SDK for Java、Tablestore SDK for Go、Tablestore SDK for Python、Tablestore SDK for Node.js、Tablestore SDK for .NET、Tablestore SDK for PHP。この例では、Tablestore SDK for Javaを使用して、集計操作を実行する方法について説明します。
最小値
フィールドの最小値を返すために使用できる集計方法です。この方法は、SQLのMIN関数と同様に使用できます。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、およびDate型のみがサポートされています。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * 各製品の価格は製品テーブルに記載されています。浙江省で生産された製品の最低価格をクエリします。 * SQLステートメント:SELECT min(column_price) FROM product where place_of_production="Zhejiang"; */ public void min(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.term("place_of_production", "Zhejiang")) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.min("min_agg_1", "column_price").missing(100)) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsMinAggregationResult("min_agg_1").getValue()); } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); TermQuery query = new TermQuery(); query.setTerm(ColumnValue.fromString("Zhejiang")); query.setFieldName("place_of_production"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.term("place_of_production", "Zhejiang").build(); searchQuery.setQuery(query); searchQuery.setLimit(0); MinAggregation aggregation = new MinAggregation(); aggregation.setAggName("min_agg_1"); aggregation.setFieldName("column_price"); aggregation.setMissing(ColumnValue.fromLong(100)); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // MinAggregation aggregation2 = AggregationBuilders.min("min_agg_1", "column_price").missing(100).build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsMinAggregationResult("min_agg_1").getValue()); } }
最大値
フィールドの最大値を返すために使用できる集計方法です。この方法は、SQLのMAX関数と同様に使用できます。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、およびDate型のみがサポートされています。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * 各製品の価格は製品テーブルに記載されています。浙江省で生産された製品の最高価格をクエリします。 * SQLステートメント:SELECT max(column_price) FROM product where place_of_production = "Zhejiang". */ public void max(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.term("place_of_production", "Zhejiang")) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.max("max_agg_1", "column_price").missing(0)) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsMaxAggregationResult("max_agg_1").getValue()); } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); TermQuery query = new TermQuery(); query.setTerm(ColumnValue.fromString("Zhejiang")); query.setFieldName("place_of_production"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.term("place_of_production", "Zhejiang").build(); searchQuery.setQuery(query); searchQuery.setLimit(0); MaxAggregation aggregation = new MaxAggregation(); aggregation.setAggName("max_agg_1"); aggregation.setFieldName("column_price"); aggregation.setMissing(ColumnValue.fromLong(100)); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // MaxAggregation aggregation2 = AggregationBuilders.max("max_agg_1", "column_price").missing(100).build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsMaxAggregationResult("max_agg_1").getValue()); } }
合計
数値フィールドのすべての値の合計を返すために使用できる集計方法です。この方法は、SQLのSUM関数と同様に使用できます。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long型とDouble型のみがサポートされています。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * 各製品の価格は製品テーブルに記載されています。浙江省で生産された製品の価格の合計をクエリします。 * SQLステートメント:SELECT sum(column_price) FROM product where place_of_production = "Zhejiang". */ public void sum(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.term("place_of_production", "Zhejiang")) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.sum("sum_agg_1", "column_number").missing(10)) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsSumAggregationResult("sum_agg_1").getValue()); } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); TermQuery query = new TermQuery(); query.setTerm(ColumnValue.fromString("Zhejiang")); query.setFieldName("place_of_production"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.term("place_of_production", "Zhejiang").build(); searchQuery.setQuery(query); searchQuery.setLimit(0); SumAggregation aggregation = new SumAggregation(); aggregation.setAggName("sum_agg_1"); aggregation.setFieldName("column_number"); aggregation.setMissing(ColumnValue.fromLong(100)); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // SumAggregation aggregation2 = AggregationBuilders.sum("sum_agg_1", "column_number").missing(10).build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsSumAggregationResult("sum_agg_1").getValue()); } }
平均値
数値フィールドのすべての値の平均を返すために使用できる集計方法です。この方法は、SQLのAVG関数と同様に使用できます。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、およびDate型のみがサポートされています。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * 各製品の売上高は製品テーブルに記載されています。浙江省で生産された製品の平均価格をクエリします。 * SQLステートメント:SELECT avg(column_price) FROM product where place_of_production = "Zhejiang". */ public void avg(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.term("place_of_production", "Zhejiang")) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.avg("avg_agg_1", "column_price")) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsAvgAggregationResult("avg_agg_1").getValue()); } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); TermQuery query = new TermQuery(); query.setTerm(ColumnValue.fromString("Zhejiang")); query.setFieldName("place_of_production"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.term("place_of_production", "Zhejiang").build(); searchQuery.setQuery(query); searchQuery.setLimit(0); AvgAggregation aggregation = new AvgAggregation(); aggregation.setAggName("avg_agg_1"); aggregation.setFieldName("column_price"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // AvgAggregation aggregation2 = AggregationBuilders.avg("avg_agg_1", "column_price").build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsAvgAggregationResult("avg_agg_1").getValue()); } }
カウント
フィールドの値の総数または検索インデックスの行の総数を返すために使用できる集計方法です。この方法は、SQLのCOUNT関数と同様に使用できます。
次の方法を使用して、検索インデックスの行の総数またはクエリ条件を満たす行の総数をクエリできます。
集計のカウント機能を使用します。リクエストでcountパラメータを*に設定します。
クエリ機能を使用して、クエリ条件を満たす行の数を取得します。クエリでsetGetTotalCountパラメータをtrueに設定します。MatchAllQueryを使用して、検索インデックスの行の総数を取得します。
列の名前をcount式の値として使用して、検索インデックス内の列を含む行の数をクエリできます。この方法は、スパース列を含むシナリオに適しています。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、Boolean、Keyword、Geo_point、およびDate型のみがサポートされています。
例
/** * 加盟店のペナルティレコードは加盟店テーブルに記録されます。浙江省に所在し、ペナルティレコードが存在する加盟店の数をクエリできます。加盟店のペナルティレコードが存在しない場合、ペナルティレコードに対応するフィールドも加盟店には存在しません。 * SQLステートメント:SELECT count(column_history) FROM product where place_of_production = "Zhejiang". */ public void count(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.term("place_of_production", "Zhejiang")) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.count("count_agg_1", "column_history")) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsCountAggregationResult("count_agg_1").getValue()); } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); TermQuery query = new TermQuery(); query.setTerm(ColumnValue.fromString("Zhejiang")); query.setFieldName("place_of_production"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.term("place_of_production", "Zhejiang").build(); searchQuery.setQuery(query); searchQuery.setLimit(0); CountAggregation aggregation = new CountAggregation(); aggregation.setAggName("count_agg_1"); aggregation.setFieldName("column_history"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // CountAggregation aggregation2 = AggregationBuilders.count("count_agg_1", "column_history").build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsCountAggregationResult("count_agg_1").getValue()); } }
個別カウント
フィールドの個別値の数を返すために使用できる集計方法です。この方法は、SQL COUNT(DISTINCT)
関数と同様に使用できます。
個別値の数は概算です。
個別カウント機能を使用する前の行の総数が10,000未満の場合、計算結果は正確な値に近くなります。
個別カウント機能を使用する前の行の総数が1億以上の場合、エラー率は約2%です。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、Boolean、Keyword、Geo_point、およびDate型のみがサポートされています。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * 製品が生産された異なる省の数をクエリします。 * SQLステートメント:SELECT count(distinct column_place) FROM product. */ public void distinctCount(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.distinctCount("dis_count_agg_1", "column_place")) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("dis_count_agg_1").getValue()); } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); MatchAllQuery query = new MatchAllQuery(); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.matchAll().build(); searchQuery.setQuery(query); searchQuery.setLimit(0); DistinctCountAggregation aggregation = new DistinctCountAggregation(); aggregation.setAggName("dis_count_agg_1"); aggregation.setFieldName("column_place"); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // DistinctCountAggregation aggregation2 = AggregationBuilders.distinctCount("dis_count_agg_1", "column_place").build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("dis_count_agg_1").getValue()); } }
パーセンタイル統計
パーセンタイル値は、データセット内の値の相対的な位置を示します。たとえば、システムの日常的なO&M中に各リクエストの応答時間に関する統計を収集する場合、p25、p50、p90、p99などのパーセンタイルを使用して応答時間の分布を分析する必要があります。
結果の精度を向上させるために、p1やp99などの極端なパーセンタイル値を指定することをお勧めします。p50などの他の値の代わりに極端なパーセンタイル値を使用すると、返される結果がより正確になります。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、およびDate型のみがサポートされています。
percentiles
p50、p90、p99などのパーセンタイル。1つ以上のパーセンタイルを指定できます。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * パーセンタイルを使用して、システムに送信される各リクエストの応答時間の分布を分析します。 */ public void percentilesAgg(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("indexName") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addAggregation(AggregationBuilders.percentiles("percentilesAgg", "latency") .percentiles(Arrays.asList(25.0d, 50.0d, 99.0d)) .missing(1.0)) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 結果を取得します。 PercentilesAggregationResult percentilesAggregationResult = resp.getAggregationResults().getAsPercentilesAggregationResult("percentilesAgg"); for (PercentilesAggregationItem item : percentilesAggregationResult.getPercentilesAggregationItems()) { System.out.println("key: " + item.getKey() + " value:" + item.getValue().asDouble()); } } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); MatchAllQuery query = new MatchAllQuery(); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.matchAll().build(); searchQuery.setQuery(query); searchQuery.setLimit(0); PercentilesAggregation aggregation = new PercentilesAggregation(); aggregation.setAggName("percentilesAgg"); aggregation.setFieldName("latency"); aggregation.setPercentiles(Arrays.asList(25.0d, 50.0d, 99.0d)); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // AggregationBuilders.percentiles("percentilesAgg", "latency").percentiles(Arrays.asList(25.0d, 50.0d, 99.0d)).missing(1.0).build(); List<Aggregation> aggregationList = new ArrayList<Aggregation>(); aggregationList.add(aggregation); searchQuery.setAggregationList(aggregationList); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 結果を取得します。 PercentilesAggregationResult percentilesAggregationResult = resp.getAggregationResults().getAsPercentilesAggregationResult("percentilesAgg"); for (PercentilesAggregationItem item : percentilesAggregationResult.getPercentilesAggregationItems()) { System.out.println("key: " + item.getKey() + " value:" + item.getValue().asDouble()); } } }
フィールド値によるグループ化
フィールド値に基づいてクエリ結果をグループ化するために使用できる集計方法です。同じ値は一緒にグループ化されます。各グループの同一の値と各グループの同一の値の数が返されます。
グループ内の値の数が非常に大きい場合、計算された数値は実際の数値と異なる場合があります。
複数のフィールドに基づいてクエリ結果をグループ化する場合は、ネストモードでgroupByパラメータを使用するか、GroupByCompositeパラメータを使用できます。groupByパラメータとGroupByCompositeパラメータの違いについては、付録:複数フィールドのグループ化のさまざまな方法を参照してください。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long、Double、Boolean、Keyword、およびDate型のみがサポートされています。
groupBySorter
グループの並べ替えルール。デフォルトでは、グループはグループ内の項目数に基づいて降順に並べ替えられます。複数の並べ替えルールを設定すると、グループはルールが設定された順序で並べ替えられます。次の並べ替えルールがサポートされています。
値でアルファベット順に並べ替える
値でアルファベットの逆順に並べ替える
行数で昇順に並べ替える
行数で降順に並べ替える
サブ集計結果から取得された値で昇順に並べ替える
サブ集計結果から取得された値で降順に並べ替える
size
返すグループの数。デフォルト値:10。最大値:2000。グループの数が2,000を超える場合、最初の2,000グループのみが返されます。
subAggregation and subGroupBy
サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。
シナリオ
各カテゴリの製品数と、各カテゴリの製品の最高価格と最低価格をクエリします。
方法
製品カテゴリ別にクエリ結果をグループ化して、各カテゴリの製品数を取得します。次に、2つのサブ集計操作を実行して、各カテゴリの製品の最高価格と最低価格を取得します。
例:
果物:5。最高価格は15人民元です。最低価格は3人民元です。
トイレタリー:10。最高価格は98人民元です。最低価格は1人民元です。
電子機器:3。最高価格は8,699人民元です。最低価格は2,300人民元です。
その他の製品:15。最高価格は1,000人民元です。最低価格は80人民元です。
例
単一フィールドによるグループ化
/** * 各カテゴリの製品数と、各カテゴリの製品の最高価格と最低価格をクエリします。 * 返される結果の例:果物:5。最高価格は15人民元で、最低価格は3人民元です。トイレタリー:10。最高価格は98人民元で、最低価格は1人民元です。電子機器:3。最高価格は8,699人民元で、最低価格は2,300人民元です。 * その他の製品:15。最高価格は1,000人民元で、最低価格は80人民元です。 */ public void groupByField(SyncClient client) { // builderを使用してクエリステートメントを作成します。 { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) // 特定のデータではなく集計結果のみを取得する場合は、limitを0に設定してクエリのパフォーマンスを向上させることができます。 .addGroupBy(GroupByBuilders .groupByField("name1", "column_type") .addSubAggregation(AggregationBuilders.min("subName1", "column_price")) .addSubAggregation(AggregationBuilders.max("subName2", "column_price")) ) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name1").getGroupByFieldResultItems()) { // 値を表示します。 System.out.println(item.getKey()); // 行数を表示します。 System.out.println(item.getRowCount()); // 最低価格を表示します。 System.out.println(item.getSubAggregationResults().getAsMinAggregationResult("subName1").getValue()); // 最高価格を表示します。 System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName2").getValue()); } } // builderを使用せずにクエリステートメントを作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); MatchAllQuery query = new MatchAllQuery(); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、TermQueryを使用してクエリステートメントを作成する方法と同じ効果があります。 // Query query2 = QueryBuilders.matchAll().build(); searchQuery.setQuery(query); searchQuery.setLimit(0); GroupByField groupByField = new GroupByField(); groupByField.setGroupByName("name1"); groupByField.setFieldName("column_type"); // サブ集計操作を設定します。 MinAggregation minAggregation = AggregationBuilders.min("subName1", "column_price").build(); MaxAggregation maxAggregation = AggregationBuilders.max("subName2", "column_price").build(); groupByField.setSubAggregations(Arrays.asList(minAggregation, maxAggregation)); // 次のコメントでは、builderを使用してクエリステートメントを作成しています。builderを使用してクエリステートメントを作成する方法は、aggregationを使用してクエリステートメントを作成する方法と同じ効果があります。 // GroupByBuilders.groupByField("name1", "column_type") // .addSubAggregation(AggregationBuilders.min("subName1", "column_price")) // .addSubAggregation(AggregationBuilders.max("subName2", "column_price").build()); List<GroupBy> groupByList = new ArrayList<GroupBy>(); groupByList.add(groupByField); searchQuery.setGroupByList(groupByList); searchRequest.setSearchQuery(searchQuery); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name1").getGroupByFieldResultItems()) { // 値を表示します。 System.out.println(item.getKey()); // 行数を表示します。 System.out.println(item.getRowCount()); // 最低価格を表示します。 System.out.println(item.getSubAggregationResults().getAsMinAggregationResult("subName1").getValue()); // 最高価格を表示します。 System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName2").getValue()); } } }
ネストモードでの複数フィールドによるグループ化
/** * ネストモードでの複数フィールドによるクエリ結果のグループ化の例。 * 検索インデックスでは、ネストモードで2つのgroupByフィールドを使用すると、SQLステートメントで複数のgroupByフィールドを使用するのと同じ効果が得られます。 * SQLステートメント:select a,d, sum(b),sum(c) from user group by a,d. */ public void GroupByMultiField() { SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .returnAllColumns(true) // returnAllColumnsをfalseに設定し、addColumesToGetに値を指定すると、クエリのパフォーマンスが向上します。 //.addColumnsToGet("col_1","col_2") .searchQuery(SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) // クエリ条件を指定します。クエリ条件は、SQLのWHERE句と同様に使用できます。QueryBuilders.bool()を使用してネストされたクエリを実行できます。 .addGroupBy( GroupByBuilders .groupByField("一意の名前_1", "field_a") .size(20) .addSubGroupBy( GroupByBuilders .groupByField("一意の名前_2", "field_d") .size(20) .addSubAggregation(AggregationBuilders.sum("一意の名前_3", "field_b")) .addSubAggregation(AggregationBuilders.sum("一意の名前_4", "field_c")) ) ) .build()) .build(); SearchResponse response = client.search(searchRequest); // 指定された条件を満たす行をクエリします。 List<Row> rows = response.getRows(); // 集計結果を取得します。 GroupByFieldResult groupByFieldResult1 = response.getGroupByResults().getAsGroupByFieldResult("一意の名前_1"); for (GroupByFieldResultItem resultItem : groupByFieldResult1.getGroupByFieldResultItems()) { System.out.println("field_a key:" + resultItem.getKey() + " Count:" + resultItem.getRowCount()); // サブ集計結果を取得します。 GroupByFieldResult subGroupByResult = resultItem.getSubGroupByResults().getAsGroupByFieldResult("一意の名前_2"); for (GroupByFieldResultItem item : subGroupByResult.getGroupByFieldResultItems()) { System.out.println("field_a " + resultItem.getKey() + " field_d key:" + item.getKey() + " Count: " + item.getRowCount()); double sumOf_field_b = item.getSubAggregationResults().getAsSumAggregationResult("一意の名前_3").getValue(); double sumOf_field_c = item.getSubAggregationResults().getAsSumAggregationResult("一意の名前_4").getValue(); System.out.println("sumOf_field_b:" + sumOf_field_b); System.out.println("sumOf_field_c:" + sumOf_field_c); } } }
集計のグループを並べ替える
/** * 集計結果から取得したグループの並べ替えルールを設定する例。 * 方法:GroupBySorterを指定して並べ替えルールを設定します。複数の並べ替えルールを設定すると、グループはルールが設定された順序で並べ替えられます。GroupBySorterは、昇順または降順での並べ替えをサポートしています。 * デフォルトでは、グループは行数で降順に並べ替えられます(GroupBySorter.rowCountSortInDesc())。 */ public void groupByFieldWithSort(SyncClient client) { // クエリステートメントを作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>.indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) .addGroupBy(GroupByBuilders .groupByField("name1", "column_type") //.addGroupBySorter(GroupBySorter.subAggSortInAsc("subName1")) // サブ集計結果から取得された値に基づいてグループを昇順に並べ替えます。 .addGroupBySorter(GroupBySorter.groupKeySortInAsc()) // 集計結果から取得された値に基づいてグループを昇順に並べ替えます。 //.addGroupBySorter(GroupBySorter.rowCountSortInDesc()) // 各グループの集計結果から取得された行数に基づいてグループを降順に並べ替えます。 .size(20) .addSubAggregation(AggregationBuilders.min("subName1", "column_price")) .addSubAggregation(AggregationBuilders.max("subName2", "column_price")) ) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); }
複数フィールドによるグループ化
複数のフィールドに基づいてクエリ結果をグループ化するために使用できる集計方法です。トークンを使用してページングを実行できます。
この機能は、Tablestore SDK for JavaとTablestore SDK for Goでのみサポートされています。
複数のフィールドに基づいてクエリ結果をグループ化する場合は、ネストモードでgroupByパラメータを使用するか、GroupByCompositeパラメータを使用できます。groupByパラメータとGroupByCompositeパラメータの違いについては、付録:複数フィールドのグループ化のさまざまな方法を参照してください。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
sources
クエリ結果をグループ化するフィールド。最大32個のフィールドでクエリ結果をグループ化し、結果のグループに対して集計操作を実行できます。次のグループタイプがサポートされています。
重要sourcesパラメータで指定されたグループタイプの場合、groupBySorterパラメータはgroupKeySortにのみ設定できます。
デフォルトでは、グループは降順に並べ替えられます。
フィールド値が存在しない場合、システムはNULLを返します。
GroupByFieldタイプの場合、設定できるパラメータはgroupByName、fieldName、groupBySorterのみです。
GroupByHistogramタイプの場合、設定できるパラメータはgroupByName、fieldName、interval、groupBySorterのみです。
GroupByDateHistogramタイプの場合、設定できるパラメータはgroupByName、fieldName、interval、timeZone、groupBySorterのみです。
nextToken
次のリクエストで使用されるページングトークン。新しいグループのページを取得するために使用されます。nextTokenパラメータの値は、GroupByCompositeResult操作の出力から取得できます。nextTokenパラメータを使用すると、すべての結果グループを取得できます。
size
ページあたりのグループ数。クエリ条件を満たすグループの数がsizeパラメータの値を超える場合は、nextTokenパラメータを使用して次のページのグループを取得できます。
重要返すグループの数を制限する場合、SizeパラメータとsuggestedSizeパラメータを同時に設定することはできません。ほとんどの場合、sizeパラメータを設定することをお勧めします。
TablestoreをApache SparkやPrestoSQLなどの高スループットコンピューティングエンジンと相互接続するシナリオでは、suggestedSizeパラメータを設定することをお勧めします。
suggestedSize
ページあたりの予想グループ数。サーバー側で許可される最大グループ数より大きい値または-1を指定できます。サーバー側は、その容量に基づいてグループの数を返します。このパラメータは、TablestoreをApache SparkやPrestoSQLなどの高スループットコンピューティングエンジンと相互接続するシナリオに適しています。
このパラメータをサーバー側で許可される最大グループ数より大きい値に設定すると、システムは値をサーバー側で許可される最大グループ数に調整します。実際に返されるグループの数は、
min(suggestedSize, サーバー側で許可される最大グループ数, グループの総数)
と同じです。subAggregation and subGroupBy
サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。
重要GroupByCompositeパラメータは、subGroupByではサポートされていません。
例
/** * クエリ結果のグループ化と集計:SourceGroupByパラメータに渡されたgroupbyField、groupByHistogram、groupByDataHistogramなどのパラメータに基づいて、クエリ結果をグループ化し、結果のグループに対して集計操作を実行します。 * 複数フィールドの集計結果をフラットな構造で返します。 */ public static void groupByComposite(SyncClient client) { GroupByComposite.Builder compositeBuilder = GroupByBuilders .groupByComposite("groupByComposite") .size(2000) .addSources(GroupByBuilders.groupByField("groupByField", "Col_Keyword") .addGroupBySorter(GroupBySorter.groupKeySortInAsc()).build()) .addSources(GroupByBuilders.groupByHistogram("groupByHistogram", "Col_Long") .addGroupBySorter(GroupBySorter.groupKeySortInAsc()) .interval(5) .build()) .addSources(GroupByBuilders.groupByDateHistogram("groupByDateHistogram", "Col_Date") .addGroupBySorter(GroupBySorter.groupKeySortInAsc()) .interval(5, DateTimeUnit.DAY) .timeZone("+05:30").build()); SearchRequest searchRequest = SearchRequest.newBuilder() .indexName("<検索インデックス名>") .tableName("<テーブル名>") .returnAllColumnsFromIndex(true) .searchQuery(SearchQuery.newBuilder() .addGroupBy(compositeBuilder.build()) .build()) .build(); SearchResponse resp = client.search(searchRequest); while (true) { if (resp.getGroupByResults() == null || resp.getGroupByResults().getResultAsMap().size() == 0) { System.out.println("groupByComposite Result is null or empty"); return; } GroupByCompositeResult result = resp.getGroupByResults().getAsGroupByCompositeResult("groupByComposite"); if(!result.getSourceNames().isEmpty()) { for (String sourceGroupByNames: result.getSourceNames()) { System.out.printf("%s\t", sourceGroupByNames); } System.out.print("rowCount\t\n"); } for (GroupByCompositeResultItem item : result.getGroupByCompositeResultItems()) { for (String value : item.getKeys()) { String val = value == null ? "NULL" : value; System.out.printf("%s\t", val); } System.out.printf("%d\t\n", item.getRowCount()); } // トークンを使用してグループをページングします。 if (result.getNextToken() != null) { searchRequest.setSearchQuery( SearchQuery.newBuilder() .addGroupBy(compositeBuilder.nextToken(result.getNextToken()).build()) .build() ); resp = client.search(searchRequest); } else { break; } } }
範囲によるグループ化
フィールドの値の範囲に基づいてクエリ結果をグループ化するために使用できる集計方法です。指定された範囲内のフィールド値は一緒にグループ化されます。各範囲の値の数が返されます。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long型とDouble型のみがサポートされています。
range[double_from, double_to)
グループ化の値の範囲。
double_fromをDouble.MIN_VALUEに設定して最小値を指定し、double_toをDouble.MAX_VALUEに設定して最大値を指定できます。
subAggregation and subGroupBy
サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。
たとえば、売上高と省別にクエリ結果をグループ化した後、指定された範囲内で売上高の割合が最も大きい省を取得できます。このクエリを実行するには、GroupByRangeでGroupByFieldを指定する必要があります。
例
/** * 売上高を[0, 1000)、[1000, 5000)、[5000, Double.MAX_VALUE)の範囲に基づいてグループ化して、各範囲の売上高を取得します。 */ public void groupByRange(SyncClient client) { // クエリステートメントを作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) .addGroupBy(GroupByBuilders .groupByRange("name1", "column_number") .addRange(0, 1000) .addRange(1000, 5000) .addRange(5000, Double.MAX_VALUE) ) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 for (GroupByRangeResultItem item : resp.getGroupByResults().getAsGroupByRangeResult("name1").getGroupByRangeResultItems()) { // 行数を表示します。 System.out.println(item.getRowCount()); } }
地理的位置によるグループ化
地理的位置から中心点までの距離に基づいてクエリ結果をグループ化するために使用できる集計方法です。指定された範囲内の距離のクエリ結果は一緒にグループ化されます。各範囲の項目数が返されます。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Geo_point型のみがサポートされています。
origin(double lat, double lon)
中心点の経度と緯度。
double latは中心点の緯度を指定します。double lonは中心点の経度を指定します。
range[double_from, double_to)
グループ化に使用される距離範囲。単位:メートル。
double_fromをDouble.MIN_VALUEに設定して最小値を指定し、double_toをDouble.MAX_VALUEに設定して最大値を指定できます。
subAggregation and subGroupBy
サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。
例
/** * ユーザーを万達広場までの地理的位置に基づいてグループ化して、各距離範囲内のユーザー数を取得します。距離範囲は[0, 1000)、[1000, 5000)、[5000, Double.MAX_VALUE)です。単位:メートル。 */ public void groupByGeoDistance(SyncClient client) { // クエリステートメントを作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) .addGroupBy(GroupByBuilders .groupByGeoDistance("name1", "column_geo_point") .origin(3.1, 6.5) .addRange(0, 1000) .addRange(1000, 5000) .addRange(5000, Double.MAX_VALUE) ) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // 集計結果を取得します。 for (GroupByGeoDistanceResultItem item : resp.getGroupByResults().getAsGroupByGeoDistanceResult("name1").getGroupByGeoDistanceResultItems()) { // 行数を表示します。 System.out.println(item.getRowCount()); } }
フィルターによるグループ化
クエリ結果をフィルタリングし、各フィルターに基づいてグループ化して、一致する結果の数を取得するために使用できる集計方法です。結果は、フィルターが指定された順序で返されます。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
filter
クエリに使用できるフィルター。結果は、フィルターが指定された順序で返されます。
subAggregation and subGroupBy
サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。
例
/** * 次のフィルターを指定して、各フィルターに一致する項目の数を取得します。売上高が100を超えている、原産地が浙江省である、説明に杭州が含まれている。 */ public void groupByFilter(SyncClient client) { // クエリステートメントを作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) .addGroupBy(GroupByBuilders .groupByFilter("name1") .addFilter(QueryBuilders.range("number").greaterThanOrEqual(100)) .addFilter(QueryBuilders.term("place","Zhejiang")) .addFilter(QueryBuilders.match("text","Hangzhou")) ) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = client.search(searchRequest); // フィルターの順序に基づいて集計結果を取得します。 for (GroupByFilterResultItem item : resp.getGroupByResults().getAsGroupByFilterResult("name1").getGroupByFilterResultItems()) { // 行数を表示します。 System.out.println(item.getRowCount()); } }
ヒストグラムによるグループ化
この集計方法は、特定のデータ間隔に基づいてクエリ結果をグループ化するために使用できます。同じ範囲内のフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Long型とDouble型のみがサポートされています。
interval
集計結果を取得するために使用されるデータ間隔。
fieldRange[min,max]
intervalパラメータと一緒に使用してグループの数を制限する範囲。
(fieldRange.max-fieldRange.min)/interval
の式を使用して決定されるグループの数は、2,000を超えることはできません。minDocCount
行の最小数。グループ内の行の数が行の最小数よりも少ない場合、そのグループの集計結果は返されません。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
例
/** * 年齢層別にユーザーの分布に関する統計を収集します。 */ public static void groupByHistogram(SyncClient client) { // クエリステートメントを作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .searchQuery( SearchQuery.newBuilder() .addGroupBy(GroupByBuilders .groupByHistogram("groupByHistogram", "age") .interval(10) .minDocCount(0L) .addFieldRange(0, 99)) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = ots.search(searchRequest); // 集計操作が実行されたときに返される結果を取得します。 GroupByHistogramResult results = resp.getGroupByResults().getAsGroupByHistogramResult("groupByHistogram"); for (GroupByHistogramItem item : results.getGroupByHistogramItems()) { System.out.println("key:" + item.getKey().asLong() + " value:" + item.getValue()); } }
日付ヒストグラムによるグループ化
特定の日付間隔に基づいてクエリ結果をグループ化するために使用できる集計方法です。同じ範囲内のフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。
この機能は、Tablestore SDK for Java V5.16.1 以降でサポートされています。
パラメータ
パラメータ
説明
groupByName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Date型のみがサポートされています。
重要検索インデックスのDate型は、Tablestore SDK for Java V5.13.9以降でサポートされています。
interval
集計結果を取得するために使用されるデータ間隔。
fieldRange[min,max]
intervalパラメータと一緒に使用してグループの数を制限する範囲。
(fieldRange.max-fieldRange.min)/interval
の式を使用して決定されるグループの数は、2,000を超えることはできません。minDocCount
行の最小数。グループ内の行の数が行の最小数よりも少ない場合、そのグループの集計結果は返されません。
missing
集計操作が実行されるフィールドのデフォルト値。フィールド値が空の行に適用されます。
missingパラメータの値を指定しない場合、行は無視されます。
missingパラメータの値を指定した場合、このパラメータの値が行のフィールド値として使用されます。
timeZone
+hh:mm
または-hh:mm
形式のタイムゾーン(例:+08:00
または-09:00
)。このパラメータは、フィールドがDate型の場合にのみ必須です。Date型のフィールドにこのパラメータが指定されていない場合、集計結果にN時間のオフセットが発生する可能性があります。timeZoneパラメータを指定することで、この問題を防ぐことができます。
例
/** * 2017年5月1日10:00:00から2017年5月21日13:00:00までのcol_dateフィールドのデータの日次分布に関する統計を収集します。 */ public static void groupByDateHistogram(SyncClient client) { // クエリステートメントを作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .returnAllColumns(false) .indexName("<検索インデックス名>") .tableName("<テーブル名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) .getTotalCount(false) .addGroupBy(GroupByBuilders .groupByDateHistogram("groupByDateHistogram", "col_date") .interval(1, DateTimeUnit.DAY) .minDocCount(1) .missing("2017-05-01 13:01:00") .fieldRange("2017-05-01 10:00", "2017-05-21 13:00:00")) .build()) .build(); // クエリステートメントを実行します。 SearchResponse resp = ots.search(searchRequest); // 集計操作が実行されたときに返される結果を取得します。 List<GroupByDateHistogramItem> items = resp.getGroupByResults().getAsGroupByDateHistogramResult("groupByDateHistogram").getGroupByDateHistogramItems(); for (GroupByDateHistogramItem item : items) { System.out.printf("millisecondTimestamp:%d, count:%d \n", item.getTimestamp(), item.getRowCount()); } }
カウント
クエリ結果をグループ化した後、各グループの行をクエリできます。この方法は、MySQLのANY_VALUE(field)と同様に使用できます。
各グループの集計操作の結果から取得された行をクエリする場合、検索インデックスにNESTED、GEOPOINT、またはARRAYフィールドが含まれていると、返される結果には主キー情報のみが含まれます。必要なフィールドを取得するには、データテーブルをクエリする必要があります。
パラメータ
パラメータ
説明
aggregationName
集計操作の一意の名前。この名前を使用して、特定の集計操作の結果をクエリできます。
limit
各グループに返される行の最大数。デフォルトでは、1行のデータのみが返されます。
sort
グループ内のデータを並べ替えるために使用される並べ替え方法。
columnsToGet
返すフィールド。検索インデックス内のフィールドのみがサポートされています。Array、Date、Geopoint、およびNestedフィールドはサポートされていません。
このパラメータの値は、SearchRequestのcolumnsToGetパラメータの値と同じです。SearchRequestのcolumnsToGetパラメータに値を指定するだけで済みます。
例
/** * 学校の活動申込書には、生徒の名前、クラス、担任教師、学級委員などの情報を指定できるフィールドが含まれています。生徒をクラス別にグループ化して、申込統計と各クラスのプロパティ情報を表示できます。 * SQLステートメント:select className, teacher, monitor, COUNT(*) as number from table GROUP BY className. */ public void testTopRows(SyncClient client) { SearchRequest searchRequest = SearchRequest.newBuilder() .indexName("<検索インデックス名>") .tableName("<テーブル名>") .searchQuery( SearchQuery.newBuilder() .query(QueryBuilders.matchAll()) .limit(0) .addGroupBy(GroupByBuilders.groupByField("groupName", "className") .size(5) // 返すグループの数を指定します。返されるグループの数の最大値については、「検索インデックスの制限」トピックのGroupByFieldによって返されるグループの数に関する説明を参照してください。 .addSubAggregation(AggregationBuilders.topRows("topRowsName") .limit(1) .sort(new Sort(Arrays.asList(new FieldSort("teacher", SortOrder.DESC)))) // 教師で降順に並べ替えます。 ) ) .build()) .addColumnsToGet(Arrays.asList("teacher", "monitor")) .build(); SearchResponse resp = client.search(searchRequest); List<GroupByFieldResultItem> items = resp.getGroupByResults().getAsGroupByFieldResult("groupName").getGroupByFieldResultItems(); for (GroupByFieldResultItem item : items) { String className = item.getKey(); long number = item.getRowCount(); List<Row> topRows = item.getSubAggregationResults().getAsTopRowsAggregationResult("topRowsName").getRows(); Row row = topRows.get(0); String teacher = row.getLatestColumn("teacher").getValue().asString(); String monitor = row.getLatestColumn("monitor").getValue().asString(); } }
ネスト
GroupByはネストをサポートしています。GroupByを使用してサブ集計操作を実行できます。
ネストを使用して、グループ内でサブ集計操作を実行できます。たとえば、最大2レベルまでネスト集計操作を実行できます。
GroupBy + SubGroupBy:項目を省と市でグループ化して、各省の各市のデータを取得します。
GroupBy + SubAggregation:項目を省別にグループ化して、各省のメトリックの最大値を取得します。
複雑なGroupBy操作の高パフォーマンスを確保するために、ネストのレベル数を少なく指定できます。詳細については、検索インデックスの制限を参照してください。
public void subGroupBy(SyncClient client) {
// クエリステートメントを作成します。
SearchRequest searchRequest = SearchRequest.newBuilder()
.indexName("index_name")
.tableName("table_name")
.returnAllColumns(true)
.searchQuery(
SearchQuery.newBuilder()
.query(QueryBuilders.match("textField", "hello"))
.limit(10)
.addAggregation(AggregationBuilders.min("name1", "fieldName1"))
.addAggregation(AggregationBuilders.max("name2", "fieldName2"))
.addGroupBy(GroupByBuilders
.groupByField("name3", "fieldName3")
.addSubAggregation(AggregationBuilders.max("subName1", "fieldName4"))
.addSubAggregation(AggregationBuilders.sum("subName2", "fieldName5"))
.addSubGroupBy(GroupByBuilders
.groupByRange("subName3", "fieldName6")
.addRange(12, 90)
.addRange(100, 900)
))
.build())
.build();
// クエリステートメントを実行します。
SearchResponse resp = client.search(searchRequest);
// 最初のレベルの最大値と最小値を取得します。
AggregationResults aggResults = resp.getAggregationResults();
System.out.println(aggResults.getAsMinAggregationResult("name1").getValue());
System.out.println(aggResults.getAsMaxAggregationResult("name2").getValue());
// 最初のレベルのGroupByField結果と、GroupByFieldにネストされた集計の結果を取得します。
GroupByFieldResult results = resp.getGroupByResults().getAsGroupByFieldResult("name3");
for (GroupByFieldResultItem item : results.getGroupByFieldResultItems()) {
System.out.println("count:" + item.getRowCount());
System.out.println("key:" + item.getKey());
// サブ集計結果を取得します。
// サブ集計操作の結果から取得された最大値を表示します。
System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName1"));
// サブ集計操作の結果から取得された合計を表示します。
System.out.println(item.getSubAggregationResults().getAsSumAggregationResult("subName2"));
// サブ集計操作の結果から取得されたGroupByRange値を表示します。
GroupByRangeResult subResults = item.getSubGroupByResults().getAsGroupByRangeResult("subName3");
for (GroupByRangeResultItem subItem : subResults.getGroupByRangeResultItems()) {
System.out.println(String.format("from:%s, to:%s, count:%s", subItem.getFrom(), subItem.getTo(), subItem.getRowCount()));
}
}
}
複数集計
複数の集計操作を実行できます。
複数の複雑な集計操作を同時に実行すると、長時間を要する場合があります。
複数集計の組み合わせ
public void multipleAggregation(SyncClient client) {
// クエリステートメントを作成します。
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<テーブル名>")
.indexName("<検索インデックス名>")
.searchQuery(
SearchQuery.newBuilder()
.query(QueryBuilders.matchAll())
.limit(0)
.addAggregation(AggregationBuilders.min("name1", "long"))
.addAggregation(AggregationBuilders.sum("name2", "long"))
.addAggregation(AggregationBuilders.distinctCount("name3", "long"))
.build())
.build();
// クエリステートメントを実行します。
SearchResponse resp = client.search(searchRequest);
// 集計操作の結果から最小値を取得します。
System.out.println(resp.getAggregationResults().getAsMinAggregationResult("name1").getValue());
// 集計操作の結果から合計を取得します。
System.out.println(resp.getAggregationResults().getAsSumAggregationResult("name2").getValue());
// 集計操作の結果から個別値の数を取得します。
System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("name3").getValue());
}
集計とグループ化の組み合わせ
public void multipleGroupBy(SyncClient client) {
// クエリステートメントを作成します。
SearchRequest searchRequest = SearchRequest.newBuilder()
.tableName("<テーブル名>")
.indexName("<検索インデックス名>")
.searchQuery(
SearchQuery.newBuilder()
.query(QueryBuilders.matchAll())
.limit(0)
.addAggregation(AggregationBuilders.min("name1", "long"))
.addAggregation(AggregationBuilders.sum("name2", "long"))
.addAggregation(AggregationBuilders.distinctCount("name3", "long"))
.addGroupBy(GroupByBuilders.groupByField("name4", "type"))
.addGroupBy(GroupByBuilders.groupByRange("name5", "long").addRange(1, 15))
.build())
.build();
// クエリステートメントを実行します。
SearchResponse resp = client.search(searchRequest);
// 集計操作の結果から最小値を取得します。
System.out.println(resp.getAggregationResults().getAsMinAggregationResult("name1").getValue());
// 集計操作の結果から合計を取得します。
System.out.println(resp.getAggregationResults().getAsSumAggregationResult("name2").getValue());
// 集計操作の結果から個別値の数を取得します。
System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("name3").getValue());
// 集計操作の結果からGroupByFieldの値を取得します。
for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name4").getGroupByFieldResultItems()) {
// キーを表示します。
System.out.println(item.getKey());
// 行数を表示します。
System.out.println(item.getRowCount());
}
// 集計操作の結果からGroupByRangeの値を取得します。
for (GroupByRangeResultItem item : resp.getGroupByResults().getAsGroupByRangeResult("name5").getGroupByRangeResultItems()) {
// 行数を表示します。
System.out.println(item.getRowCount());
}
}
付録:複数フィールドのグループ化のさまざまな方法
複数のフィールドに基づいてクエリ結果をグループ化する場合は、ネストモードでgroupByパラメータを使用するか、GroupByCompositeパラメータを使用できます。次の表は、ネストモードのgroupByパラメータとgroupByCompositeパラメータの違いについて説明しています。
機能 | groupBy (ネスト) | groupByComposite |
サイズ | 2000 | 2000 |
フィールドの制限 | 最大5レベルがサポートされています。 | 最大32レベルがサポートされています。 |
ページング | サポートされていません | nextTokenパラメータを使用してサポートされています |
グループ内の行の並べ替えルール |
| アルファベット順またはアルファベットの逆順 |
集計のサポート | はい | はい |
互換性 | Date型のフィールドの場合、クエリ結果は指定された形式で返されます。 | DATE型のフィールドの場合、クエリ結果はタイムスタンプ文字列として返されます。 |