このトピックでは、集計操作を実行してデータを分析する方法について説明します。集計操作を実行して、行の最小値、最大値、合計、平均値、カウント、個別カウント、およびパーセンタイル統計を取得できます。また、集計操作を実行して、フィールド値、範囲、地理的位置、フィルター、ヒストグラム、または日付ヒストグラム別に結果をグループ化し、ネストされたクエリを実行し、各グループの集計操作の結果から取得された行をクエリすることもできます。複雑なクエリに対して複数の集計操作を実行できます。
手順
次の図は、完全な集計手順を示しています。

サーバーは、クエリ条件を満たすデータをクエリし、リクエストに基づいてデータの集計を実行します。したがって、集計を必要とするリクエストは、集計を必要としないリクエストよりも処理が複雑になります。
特徴
集計は、SQL 関数と同様の複数の機能をサポートしています。たとえば、最小値を取得するために使用できる MIN() 関数、最大値を取得するために使用できる MAX() 関数、合計を取得するために使用できる SUM() 関数、平均値を取得するために使用できる AVG() 関数、行数を取得するために使用できる COUNT() 関数、個別行数を取得するために使用できる COUNT(DISTINCT) 関数、各グループの集計操作の結果から取得された行をクエリするために使用できる ANY_VALUE() 関数、およびクエリ結果をグループ化するために使用できる GROUP BY 関数などです。また、集計操作を実行して、パーセンタイル統計を取得したり、フィールド値、範囲、地理的位置、フィルター、ヒストグラム、または日付ヒストグラム別に結果をグループ化したり、複数のフィールドに基づいて結果をグループ化したり、ネストされたクエリを実行したりすることもできます。次の表に、これらの機能を示します。
機能 | 説明 |
最小値 | フィールドの最小値を返すために使用できる集計方法。この方法は、SQL MIN 関数と同様の方法で使用できます。 |
最大値 | フィールドの最大値を返すために使用できる集計方法。この方法は、SQL MAX 関数と同様の方法で使用できます。 |
合計 | 数値フィールドのすべての値の合計を返すために使用できる集計方法。この方法は、SQL SUM 関数と同様の方法で使用できます。 |
平均値 | 数値フィールドのすべての値の平均を返すために使用できる集計方法。この方法は、SQL AVG 関数と同様の方法で使用できます。 |
カウント | フィールドの値の総数または検索インデックスの行の総数を返すために使用できる集計方法。この方法は、SQL COUNT 関数と同様の方法で使用できます。 |
個別カウント | フィールドの個別値の数を返すために使用できる集計方法。この方法は、SQL COUNT(DISTINCT) 関数と同様の方法で使用できます。 |
パーセンタイル統計 | パーセンタイル値は、データセット内の値の相対位置を示します。たとえば、システムのルーチン O&M 中に各リクエストの応答時間に関する統計を収集する場合、p25、p50、p90、p99 などのパーセンタイルを使用して応答時間の分布を分析する必要があります。 |
フィールド値によるグループ化 | フィールド値に基づいてクエリ結果をグループ化するために使用できる集計方法。同じ値は一緒にグループ化されます。各グループの同一の値と各グループの同一の値の数が返されます。 |
GroupBy でのネスト | GroupBy はネストをサポートしています。GroupBy を使用して、サブ集計操作を実行できます。 |
複数のフィールドによるグループ化 | 複数のフィールドに基づいてクエリ結果をグループ化するために使用できる集計方法。トークンを使用してページングを実行できます。 |
範囲によるグループ化 | フィールドの値の範囲に基づいてクエリ結果をグループ化するために使用できる集計方法。特定の範囲内にあるフィールド値は一緒にグループ化されます。各範囲の値の数が返されます。 |
地理的位置によるグループ化 | 地理的位置から中心点までの距離に基づいてクエリ結果をグループ化するために使用できる集計方法。特定の範囲内にある距離のクエリ結果は一緒にグループ化されます。各範囲の値の数が返されます。 |
フィルターによるグループ化 | クエリ結果をフィルタリングしてグループ化し、各フィルターに一致する結果の数を取得するために使用できる集計方法。結果は、フィルターが指定された順序で返されます。 |
ヒストグラムによるクエリ | 特定のデータ間隔に基づいてクエリ結果をグループ化するために使用できる集計方法。同じ範囲内にあるフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。 |
日付ヒストグラムによるクエリ | 特定の日付間隔に基づいてクエリ結果をグループ化するために使用できる集計方法。同じ範囲内にあるフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。 |
各グループの集計操作の結果から取得された行をクエリする | クエリ結果をグループ化した後、各グループの行をクエリできます。この方法は、MySQL の ANY_VALUE(field) 関数と同様の方法で使用できます。 |
複数の集計 | 複数の集計操作を実行できます。 説明 複数の複雑な集計操作を同時に実行すると、長時間がかかる場合があります。 |
関連 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 インスタンスが初期化されている。詳細については、「Tablestore クライアントを初期化する」をご参照ください。
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 を使用して、集計操作を実行できます。Java 用 Tablestore SDK、Go 用 Tablestore SDK、Python 用 Tablestore SDK、Node.js 用 Tablestore SDK、.NET 用 Tablestore SDK、PHP 用 Tablestore SDK。この例では、Java 用 Tablestore SDK を使用します。
集計機能でサポートされるフィールドタイプは、検索インデックスでサポートされるフィールドタイプです。検索インデックスでサポートされるフィールドタイプと、検索インデックスでサポートされるフィールドタイプとデータテーブルでサポートされるフィールドタイプのマッピングについては、「データ型」をご参照ください。
最小値
フィールドの最小値を返すために使用できる集計方法。この方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } //ビルダーを使用せずにクエリ文を作成します。 { 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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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)); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } //ビルダーを使用せずにクエリ文を作成します。 { 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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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)); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } // ビルダーを使用せずにクエリ文を作成します。 { 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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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)); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } //ビルダーを使用せずにクエリ文を作成します。 { 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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } //ビルダーを使用せずにクエリ文を作成します。 { 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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } //ビルダーを使用せずにクエリ文を作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); MatchAllQuery query = new MatchAllQuery(); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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"); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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) { //ビルダーを使用してクエリ文を作成します。 { 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()); } } //ビルダーを使用せずにクエリ文を作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); MatchAllQuery query = new MatchAllQuery(); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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)); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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
グループの並べ替えルール。デフォルトでは、グループはグループ内のアイテムの数に基づいて降順に並べ替えられます。複数の並べ替えルールを構成すると、グループはルールが構成された順序で並べ替えられます。次の並べ替えルールがサポートされています。
groupKeySortInAsc: 値でアルファベット順に並べ替えます。
groupKeySortInDesc: 値で逆アルファベット順に並べ替えます。
rowCountSortInAsc: 行数で昇順に並べ替えます。
rowCountSortInDesc (デフォルト): 行数で降順に並べ替えます。
subAggSortInAsc: サブ集計結果から取得された値で昇順に並べ替えます。
subAggSortInDesc: サブ集計結果から取得された値で降順に並べ替えます。
size
返すグループの数。デフォルト値: 10。最大値: 2000。
subAggregations
各グループのデータに対して実行できるサブ集計操作 (最大値、合計、または平均値の計算など)。
subGroupBys
各親グループのデータをさらにグループ化するために、各親グループのデータに対して実行できるサブグループ化操作。
例
単一フィールドによるグループ化
/** * 各カテゴリの製品数、製品の最高価格、および最低価格をクエリします。 * 返される結果の例: 果物: 5。最高価格は 15 人民元、最低価格は 3 人民元です。トイレタリー: 10。最高価格は 98 人民元、最低価格は 1 人民元です。電子機器: 3。最高価格は 8,699 人民元、最低価格は 2,300 人民元です。その他の製品: 15。最高価格は 1,000 人民元、最低価格は 80 人民元です。 */ public void groupByField(SyncClient client) { //ビルダーを使用してクエリ文を作成します。 { 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()); } } //ビルダーを使用せずにクエリ文を作成します。 { SearchRequest searchRequest = new SearchRequest(); searchRequest.setTableName("<テーブル名>"); searchRequest.setIndexName("<検索インデックス名>"); SearchQuery searchQuery = new SearchQuery(); MatchAllQuery query = new MatchAllQuery(); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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)); //次のコメントでは、ビルダーを使用してクエリ文を作成しています。ビルダーを使用してクエリ文を作成する方法は、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(SyncClient client) { 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); }
GroupBy でのネスト
GroupBy はネストをサポートしています。GroupBy を使用して、サブ集計操作を実行できます。
パフォーマンスと複雑さのバランスをとるために、許可されるネストレイヤー数は限られています。詳細については、「検索インデックスの制限」をご参照ください。
一般的なシナリオ
複数レベルのグループ化 (GroupBy + SubGroupBy)
最初のレベルでデータをグループ化した後、2 番目のレベルのグループ化を実行できます。たとえば、最初にデータを県でグループ化し、次に市でグループ化して、各県の各市のデータを取得できます。
グループ化に続く集計 (GroupBy + SubAggregation)
最初のレベルでデータをグループ化した後、各グループのデータに対して集計操作 (最大値または平均値の計算など) を実行できます。たとえば、データを県でグループ化した後、各県グループの特定の指標の最大値を取得できます。
例
次の例は、県と市でネストされたグループ化を実行し、各県の注文の総数と、各市の注文の総数と注文の最大金額を計算する方法を示しています。
public static void subGroupBy(SyncClient client) { //クエリ文を作成します。 SearchRequest searchRequest = SearchRequest.newBuilder() .tableName("<テーブル名>") .indexName("<検索インデックス名>") .returnAllColumns(true) .searchQuery(SearchQuery.newBuilder() .query(QueryBuilders.matchAll()).limit(20) //最初のレベルのグループ化: 県でグループ化し、各県の注文 ID の数 (注文の総数) をカウントします。 //2 番目のレベルのグループ化: 市でグループ化し、各市の注文 ID の数 (注文の総数) をカウントし、各市の注文の最大金額を計算します。 .addGroupBy(GroupByBuilders.groupByField("provinceName", "province") .addSubAggregation(AggregationBuilders.count("provinceOrderCounts", "order_id")) .addGroupBySorter(GroupBySorter.rowCountSortInDesc()) .addSubGroupBy(GroupByBuilders.groupByField("cityName", "city") .addSubAggregation(AggregationBuilders.count("cityOrderCounts", "order_id")) .addSubAggregation(AggregationBuilders.max("cityMaxAmount", "order_amount")) .addGroupBySorter(GroupBySorter.subAggSortInDesc("cityMaxAmount")))) .build()) .build(); //クエリ文を実行します。 SearchResponse resp = client.search(searchRequest); //最初のレベルのグループ化結果 (各県の注文の総数) を取得します GroupByFieldResult results = resp.getGroupByResults().getAsGroupByFieldResult("provinceName"); for (GroupByFieldResultItem item : results.getGroupByFieldResultItems()) { System.out.println("県:" + item.getKey() + "\t注文の総数:" + item.getSubAggregationResults().getAsCountAggregationResult("provinceOrderCounts").getValue()); //2 番目のレベルのグループ化結果 (各市の注文の総数と注文の最大金額) を取得します GroupByFieldResult subResults = item.getSubGroupByResults().getAsGroupByFieldResult("cityName"); for (GroupByFieldResultItem subItem : subResults.getGroupByFieldResultItems()) { System.out.println("\t(市)" + subItem.getKey() + "\t注文の総数:" + subItem.getSubAggregationResults().getAsCountAggregationResult("cityOrderCounts").getValue() + "\t注文の最大金額:" + subItem.getSubAggregationResults().getAsMaxAggregationResult("cityMaxAmount").getValue()); } } }
複数フィールドによるグループ化
複数のフィールドに基づいてクエリ結果をグループ化するために使用できる集計方法。トークンを使用してページングを実行できます。
この機能は、Java および Go 用 Tablestore SDK のみでサポートされています。
パラメーター
パラメーター
説明
groupByName
集計操作の一意の名前。この名前に基づいて、特定の集計操作の結果をクエリできます。
sources
クエリ結果をグループ化するフィールド。最大 32 のフィールドでクエリ結果をグループ化し、結果のグループに対して集計操作を実行できます。次のグループタイプがサポートされています。
GroupByField: フィールド値によるグループ化。groupByName、fieldName、および groupBySorter パラメーターを構成できます。
GroupByHistogram: ヒストグラムによるクエリ。groupByName、fieldName、interval、および groupBySorter パラメーターを構成できます。
GroupByDateHistogram: 日付ヒストグラムによるクエリ。groupByName、fieldName、interval、timeZone、および groupBySorter パラメーターを構成できます。
重要sources のグループアイテムの場合、辞書順でのグループ値 (groupKeySort) による並べ替えのみがサポートされています。デフォルトでは、グループは降順に並べ替えられます。
特定の列のフィールド値が存在しない場合、返される結果の値は NULL になります。
nextToken
データの次のページを取得するために使用されるページネーショントークン。デフォルトでは、このパラメーターは空です。
最初のリクエストでは、nextToken を空に設定します。クエリ条件を満たすすべてのデータが 1 つのリクエストで返されない場合、レスポンスの nextToken パラメーターは空ではありません。この nextToken をページネーションクエリに使用できます。
説明nextToken を永続化するか、フロントエンドページに送信する必要がある場合は、保存または送信する前に、Base64 エンコーディングを使用して nextToken を文字列としてエンコードすることをお勧めします。nextToken 自体は文字列ではありません。エンコードに new String(nextToken) を直接使用すると、トークン情報が失われます。
size
ページあたりのグループ数。デフォルト値: 10。最大値: 2000。
重要返すグループの数を制限する場合は、ほとんどの場合、size パラメーターを構成することをお勧めします。
size パラメーターと suggestedSize パラメーターを同時に構成することはできません。
suggestedSize
返すグループの数。サーバー側で許可される最大グループ数より大きい値または -1 を指定できます。サーバー側は、その容量に基づいてグループの数を返します。
このパラメーターをサーバー側で許可される最大グループ数より大きい値に設定すると、システムは値をサーバー側で許可される最大グループ数に調整します。実際に返されるグループの数は、min(suggestedSize, サーバー側で許可される最大グループ数, グループの総数) と等しくなります。
重要このパラメーターは、Tablestore を Apache Spark や PrestoSQL などの高スループットコンピューティングエンジンと相互接続する場合に適しています。
subAggregations
各グループのデータに対して実行できるサブ集計操作 (最大値、合計、または平均値の計算など)。
subGroupBys
各親グループのデータをさらにグループ化するために、各親グループのデータに対して実行できるサブグループ化操作。
重要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()); } }
日付ヒストグラムによるグループ化
特定の日付間隔に基づいてクエリ結果をグループ化するために使用できる集計方法。同じ範囲内にあるフィールド値は一緒にグループ化されます。各グループの値の範囲と各グループの値の数が返されます。
この機能は、Java 用 Tablestore SDK V5.16.1 以降でサポートされています。Java 用 Tablestore SDK のバージョン履歴については、「Java 用 Tablestore SDK のバージョン履歴」をご参照ください。
パラメーター
パラメーター
説明
groupByName
集計操作の一意の名前。この名前に基づいて、特定の集計操作の結果をクエリできます。
fieldName
集計操作を実行するために使用されるフィールドの名前。Date タイプのみがサポートされます。
重要検索インデックスの Date タイプは、Java 用 Tablestore SDK 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(); } }
複数の集計
複数の集計操作を実行できます。
複数の複雑な集計操作を同時に実行すると、長時間がかかる場合があります。
複数の集計を組み合わせる
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());
}集計と GroupBy を組み合わせる
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 (ネスト) | 複数フィールドグループ化 |
サイズ | 2000 | 2000 |
フィールドの制限 | 最大 3 レベルがサポートされています。 | 最大 32 レベルがサポートされています。 |
ページネーション | サポートされていません | nextToken パラメーターによってサポートされています |
グループ内の行の並べ替えルール |
| アルファベット順または逆アルファベット順 |
集計のサポート | はい | はい |
互換性 | Date タイプのフィールドの場合、クエリ結果は指定された形式で返されます。 | DATE タイプのフィールドの場合、クエリ結果はタイムスタンプ文字列として返されます。 |