すべてのプロダクト
Search
ドキュメントセンター

Tablestore:集計

最終更新日:Dec 28, 2024

集計操作を実行して、行の最小値、最大値、合計、平均値、カウントと個別カウント、およびパーセンタイル統計を取得できます。また、集計操作を実行して、フィールド値、範囲、地理的位置、フィルター、ヒストグラム、または日付ヒストグラム別に結果をグループ化し、ネストされたクエリを実行することもできます。複雑なクエリに対して複数の集計操作を実行できます。

手順

次の図は、完全な集計手順を示しています。

fig_agg_pro

サーバーは、クエリ条件を満たすデータをクエリし、リクエストに基づいてデータの集計を実行します。そのため、集計を必要とするリクエストは、集計を必要としないリクエストよりも複雑です。

背景情報

次の表は、集計方法について説明しています。

方法

説明

最小値

フィールドの最小値を返すために使用できる集計方法。この方法は、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 を使用してサブ集計操作を実行できます。

複数の集計

複数の集計操作を実行できます。

説明

複数の複雑な集計操作を同時に実行すると、長時間を要する場合があります。

前提条件

  • OTSClient インスタンスが初期化されていること。詳細については、OTSClient インスタンスの初期化を参照してください。

  • データテーブルが作成され、データがデータテーブルに書き込まれていること。詳細については、データテーブルの作成データの書き込みを参照してください。

  • データテーブルの検索インデックスが作成されていること。詳細については、検索インデックスの作成を参照してください。

    重要

    集計機能でサポートされているフィールドタイプは、検索インデックスでサポートされているフィールドタイプです。検索インデックスでサポートされているフィールドタイプと、検索インデックスでサポートされているフィールドタイプとデータテーブルでサポートされているフィールドタイプのマッピングについては、データ型を参照してください。

最小値

フィールドの最小値を返すために使用できる集計方法。この方法は、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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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 および 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("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .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("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            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("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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 パラメーターを使用するか、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

    次のリクエストで使用されるページングトークン。新しいグループのページを取得するために使用されます。GroupByCompositeResult 操作の出力から nextToken パラメーターの値を取得できます。nextToken パラメーターを使用すると、すべての結果のグループを取得できます。

    size

    ページあたりのグループの数。クエリ条件を満たすグループの数が size パラメーターの値を超える場合、nextToken パラメーターを使用して次のページのグループを取得できます。

    重要

    返されるグループの数を制限する場合、Size パラメーターと suggestedSize パラメーターを同時に設定することはできません。ほとんどの場合、size パラメーターを設定することをお勧めします。

    Tablestore を Apache Spark や PrestoSQL などの高スループットコンピューティングエンジンに接続する場合、suggestedSize パラメーターを設定することをお勧めします。

    suggestedSize

    ページあたりのグループの予想数。サーバー側で許可されるグループの最大数より大きい値または -1 を指定できます。サーバー側は、その容量に基づいてグループの数を返します。このパラメーターは、Tablestore を Apache Spark や PrestoSQL などの高スループットコンピューティングエンジンに接続するシナリオに適しています。

    このパラメーターをサーバー側で許可されるグループの最大数より大きい値に設定すると、システムは値をサーバー側で許可されるグループの最大数に調整します。実際に返されるグループの数は、min(suggestedSize, サーバー側で許可されるグループの最大数, グループの総数) となります。

    subAggregation および 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("<SEARCH_INDEX_NAME>")
                .tableName("<TABLE_NAME>")
                .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 および subGroupBy

    サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。

    たとえば、売上高と都道府県別にクエリ結果をグループ化した後、指定された範囲で売上高の割合が最も大きい都道府県を取得できます。このクエリを実行するには、GroupByRange で GroupByField を指定する必要があります。

  • /**
     * 売上高を [0, 1000)、[1000, 5000)、および [5000, Double.MAX_VALUE) の範囲に基づいてグループ化して、各範囲の売上高を取得します。
     */
    public void groupByRange(SyncClient client) {
        // クエリステートメントを作成します。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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 および subGroupBy

    サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。

  • /**
     * ユーザーを万達広場までの地理的位置に基づいてグループ化して、各距離範囲のユーザー数を取得します。距離範囲は [0, 1000)、[1000, 5000)、および [5000, Double.MAX_VALUE) です。単位:メートル。
     */
    public void groupByGeoDistance(SyncClient client) {
        // クエリステートメントを作成します。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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 および subGroupBy

    サブ集計操作。グループ化結果に基づいてサブ集計操作を実行できます。

  • /**
     * 次のフィルターを指定して、各フィルターに一致するアイテムの数を取得します。売上高が 100 を超える、原産地が浙江省である、説明に杭州が含まれる。
     */
    public void groupByFilter(SyncClient client) {
        // クエリステートメントを作成します。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .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 以降でサポートされています。Tablestore SDK for Java のバージョン履歴については、Tablestore SDK for Java のバージョン履歴をご参照ください。

  • パラメーター

    パラメーター

    説明

    groupByName

    集計操作の一意の名前。この名前を使用して特定の集計操作の結果をクエリできます。

    fieldName

    集計操作を実行するために使用されるフィールドの名前。Date タイプのみがサポートされています。

    重要

    検索インデックスの Date タイプは、Java V5.13.9 以降向けの Tablestore SDK でサポートされています。

    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("<SEARCH_INDEX_NAME>")
        .tableName("<TABLE_NAME>")
        .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("<SEARCH_INDEX_NAME>")
                .tableName("<TABLE_NAME>")
                .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("<SEARCH_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("<TABLE_NAME>")
        .indexName("<SEARCH_INDEX_NAME>")
        .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("<TABLE_NAME>")
        .indexName("<SEARCH_INDEX_NAME>")
        .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 タイプのフィールドの場合、クエリ結果はタイムスタンプ文字列として返されます。

参考資料

次のトピックも参照して、データテーブルのデータをクエリおよび分析できます。

  • Tablestore の SQL クエリ機能を使用します。詳細については、SQL クエリを参照してください。

  • Tablestore を DataWorks などのビッグデータプラットフォームに接続して、SQL クエリを実行し、データを分析します。詳細については、ビッグデータサービスとの接続を参照してください。

  • Tablestore を MaxCompute、Spark、Hive、HadoopMR、Function Compute、Flink、PrestoDB などのコンピューティングエンジンに接続して、SQL クエリを実行し、データを分析します。詳細については、概要を参照してください。