多次元インデックスの集約機能を使用すると、クエリ結果に対して値の計算やグループ化統計を実行できます。値の集約には、最小値、最大値、合計、平均値、カウント、個別カウント、パーセンタイル統計が含まれます。グループ化集約は、フィールド値、範囲、地理的位置、フィルター、ヒストグラム、複合集約によるグループ化をサポートしています。1 つのリクエストで複数の集約を組み合わせることができます。
集約機能は、Python SDK V5.2.1 以降でサポートされています。
特徴
次の表に、集約機能について説明します。
値の集約
特徴 | 説明 |
最小値 | フィールドから最小値を返します。SQL の |
最大値 | フィールドから最大値を返します。SQL の |
合計 | 数値フィールドの値の合計を返します。SQL の |
平均値 | 数値フィールドの値の平均を返します。SQL の |
カウント | SQL の |
個別カウント | 指定されたフィールドの個別値の数を返します。SQL の |
パーセンタイル統計 | データセットのパーセンタイル分布を計算します。例えば、通常のシステム運用保守 (O&M) 中に、この機能を使用してリクエストレイテンシーの分布 (P25、P50、P90、P99 値など) を分析できます。 |
グループ化集約
特徴 | 説明 |
フィールド値によるグループ化 | フィールドの値に基づいてクエリ結果をグループ化します。同じフィールド値を持つ行は同じグループに配置されます。応答では、各グループの値とその行数が返されます。 説明 グループ数が多い場合、この集約の結果は近似値になることがあります。 |
範囲によるグループ化 | フィールドの指定された範囲に基づいてクエリ結果をグループ化します。同じ範囲に収まるフィールド値を持つ行は同じグループに配置されます。応答では、各範囲の項目数が返されます。 |
地理的位置によるグループ化 | 中心点からの距離に基づいてクエリ結果をグループ化します。同じ距離範囲内にある行は同じグループに配置されます。応答では、各範囲の項目数が返されます。 |
フィルターによるグループ化 | 一連のフィルターに基づいてクエリ結果をグループ化します。応答では、各フィルターに一致するドキュメントの数が返されます。結果は、フィルターが指定された順序と同じ順序で返されます。 |
ヒストグラム集約 | 指定された数値間隔に基づいてクエリ結果をグループ化します。同じ間隔に収まるフィールド値を持つ行は同じグループに配置されます。応答では、各グループの値とそれに対応するカウントが返されます。 |
複合集約 | SQL の |
値の集約
最小値
フィールドから最小値を返します。SQL の min 関数に似ています。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約するフィールド。フィールドのデータの型は Long、Double、または Date である必要があります。 |
missing | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
18 歳の人々の最小スコアを計算します。
query = TermQuery('age', 18)
agg = Min('score', name='min')
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s, value: %s" % (agg_result.name, str(agg_result.value)))最大値
フィールドから最大値を返します。SQL の max 関数に似ています。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約するフィールド。フィールドのデータの型は Long、Double、または Date である必要があります。 |
missing | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
18 歳の人々の最大スコアを計算します。スコアがない場合は、デフォルト値の 0 が使用されます。
query = TermQuery('age', 18)
agg = Max('score', missing_value=0, name='max')
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s, value: %s" % (agg_result.name, str(agg_result.value)))合計
数値フィールドの値の合計を返します。SQL の sum 関数に似ています。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約するフィールド。フィールドのデータの型は Long または Double である必要があります。 |
missing | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
18 歳の人々のすべてのスコアの合計を計算します。
query = TermQuery('age', 18)
agg = Sum('score', name='sum')
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s, value: %s" % (agg_result.name, str(agg_result.value)))平均値
数値フィールドの値の平均を返します。SQL の avg 関数に似ています。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約するフィールド。フィールドのデータの型は Long、Double、または Date である必要があります。 |
missing | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
18 歳の人々の平均スコアを計算します。
query = TermQuery('age', 18)
agg = Avg('score', name='avg')
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s, value: %s" % (agg_result.name, str(agg_result.value)))カウント
指定されたフィールドの値の数、または多次元インデックス内の合計行数を返します。SQL の count 関数に似ています。
クエリに一致する行をカウントするには、2 つの方法があります:
一致する行の総数を取得するには、
get_total_countクエリパラメーターをTrueに設定します。特定のフィールドに値がある行のみをカウントする場合 (スパースな列に便利)、そのフィールドで
count集約を使用します。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約に使用されるフィールド。フィールドのデータの型は Long、Double、Boolean、Keyword、 |
例
18 歳で、試験のスコアが記録されている人の数をカウントします。
query = TermQuery('age', 18)
agg = Count('score', name='count')
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s, value: %s" % (agg_result.name, str(agg_result.value)))個別カウント
指定されたフィールドの個別値の数を返します。SQL の count(distinct) 関数に似ています。
個別カウントの結果は近似値です。
個別カウントが 10,000 未満の場合、結果はほぼ正確です。
個別カウントが 1 億に達すると、誤差率は約 2% になります。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約に使用されるフィールド。フィールドのデータの型は Long、Double、Boolean、Keyword、 |
missing | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
18 歳の人々の間で、異なる名前の数をカウントします。
query = TermQuery('age', 18)
agg = DistinctCount('name', name='distinct_name')
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s, value: %s" % (agg_result.name, str(agg_result.value)))パーセンタイル統計
データセットのパーセンタイル分布を計算します。例えば、通常のシステム運用保守中に、この機能を使用してリクエストレイテンシーの分布 (P25、P50、P90、P99 値など) を分析できます。
パーセンタイル統計は近似値です。精度は、分布の両端 (1% や 99% など) のパーセンタイルの方が、中央 (50% など) のパーセンタイルよりも高くなります。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約に使用されるフィールド。フィールドのデータの型は Long、Double、または Date である必要があります。 |
percentiles | パーセンタイル値のリスト (例: |
missing_value | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
query = TermQuery('product', '10010')
agg = Percentiles('latency', percentiles_list=[50, 90, 95])
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, aggs=[agg]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for agg_result in search_response.agg_results:
print("name: %s" % agg_result.name)
for item in agg_result.value:
print(" percentile: %s, value: %s" % (str(item.key), str(item.value)))グループ化集約
フィールド値によるグループ化
フィールドの値に基づいてクエリ結果をグループ化します。同じフィールド値を持つ行は同じグループに配置されます。応答では、各グループの値とその行数が返されます。
グループ数が多い場合、この集約の結果は近似値になることがあります。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | グループ化するフィールド。フィールドのデータの型は Long、Double、Boolean、Keyword、または Date である必要があります。 |
size | 返すグループの数。デフォルト値は 10 です。最大値は 2,000 です。グループ数が 2,000 を超える場合、最初の 2,000 グループのみが返されます。 |
group_by_sort | 返されるグループのソートルール。デフォルトでは、グループは行数の降順でソートされます。複数のルールが設定されている場合、それらは順次適用されます。グループキーの辞書順、行数、またはサブ集約の結果の昇順または降順でソートできます。 |
sub_aggs and sub_group_bys | グループ化されたデータに対してさらなる分析を行うサブ集約およびサブグループ化。例えば、プロダクトをカテゴリ別にグループ化した後、 |
例 1
18 歳の人々をスコアでグループ化し、最も一般的な 10 のスコアと各スコアの人数を取得します。
query = TermQuery('age', 18)
group_by = GroupByField('score', size=10)
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" key: %s, count: %d" % (item.key, item.row_count))例 2
18 歳の人々をスコアでグループ化し、最も一般的でない 2 つのスコアと各スコアの人数を取得します。
group_by = GroupByField('score', size=2, group_by_sort=[RowCountSort(sort_order=SortOrder.ASC)])
search_response = client.search(table_name, index_name,
SearchQuery(TermQuery('age', 18), limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" key: %s, count: %d" % (item.key, item.row_count))例 3
18 歳の人々をスコアでグループ化し、最も一般的な 2 つのスコアとそのカウントを取得し、その後、各グループの上位 3 人の情報をプライマリキーでソートして取得します。
sort = RowCountSort(sort_order=SortOrder.DESC)
sub_agg = [TopRows(limit=3, sort=Sort([PrimaryKeySort(sort_order=SortOrder.DESC)]), name='top_rows')]
group_by = GroupByField('score', size=2, group_by_sort=[sort], sub_aggs=sub_agg)
search_response = client.search(table_name, index_name,
SearchQuery(TermQuery('age', 18), limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" key: %s, count: %d" % (item.key, item.row_count))
for sub_agg in item.sub_aggs:
print(" sub_agg: %s" % sub_agg.name)
for entry in sub_agg.value:
print(" value: %s" % str(entry))例 4
18 歳の人々をスコアと性別でグループ化します。
sort = RowCountSort(sort_order=SortOrder.ASC)
sub_group = GroupByField('sex', size=10, group_by_sort=[sort])
group_by = GroupByField('score', size=10, group_by_sort=[sort], sub_group_bys=[sub_group])
search_response = client.search(table_name, index_name,
SearchQuery(TermQuery('age', 18), limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" key: %s, count: %d" % (item.key, item.row_count))
for sub_group in item.sub_group_bys:
print(" sub_group: %s" % sub_group.name)
for sub_item in sub_group.items:
print(" key: %s, count: %s" % (str(sub_item.key), str(sub_item.row_count)))範囲によるグループ化
フィールドの指定された範囲に基づいてクエリ結果をグループ化します。同じ範囲に収まるフィールド値を持つ行は同じグループに配置されます。応答では、各範囲の項目数が返されます。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | グループ化するフィールド。フィールドのデータの型は Long または Double である必要があります。 |
range[double_from, double_to) | グループ化の範囲。開始値と終了値を設定して、負の無限大と正の無限大を表すことができます。 |
sub_aggs and sub_group_bys | グループ化されたデータに対してさらなる分析を行うサブ集約およびサブグループ化。例えば、特定の売上ボリューム範囲内でどの都道府県が最も売上に貢献しているかを見つけるには、売上ボリュームでグループ化し、その後、都道府県のサブグループ化として |
例
18 歳で、スコアが [80, 90) および [90, 100) の範囲にある人々の数をカウントします。
query = TermQuery('age', 18)
group_by = GroupByRange(field_name='score', ranges=[(80, 90), (90, 100)])
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" range: %.1f~%.1f, count: %d" % (item.range_from, item.range_to, item.row_count))地理的位置によるグループ化
中心点からの距離に基づいてクエリ結果をグループ化します。同じ距離範囲内にある行は同じグループに配置されます。応答では、各範囲の項目数が返されます。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | フィールドは |
origin(double lat, double lon) | 中心点の緯度と経度。 |
range[double_from, double_to) | グループ化の範囲 (メートル単位)。開始値と終了値を設定して、負の無限大と正の無限大を表すことができます。 |
sub_aggs and sub_group_bys | グループ化されたデータに対してさらなる分析を行うサブ集約およびサブグループ化。 |
例
18 歳で、学校から 1 キロメートル以内、および 1〜2 キロメートルの範囲に自宅がある人々の数をカウントします。学校の座標は (31, 116) です。
query = TermQuery('age', 18)
group_by = GroupByGeoDistance(field_name='address', origin=GeoPoint(31, 116), ranges=[(0, 1000), (1000, 2000)])
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" range: %.1f~%.1f, count: %d" % (item.range_from, item.range_to, item.row_count))フィルターによるグループ化
一連のフィルターに基づいてクエリ結果をグループ化します。応答では、各フィルターに一致するドキュメントの数が返されます。結果は、フィルターが指定された順序と同じ順序で返されます。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
filter | フィルター条件。結果は、フィルターが指定された順序と同じ順序で返されます。 |
sub_aggs and sub_group_bys | グループ化されたデータに対してさらなる分析を行うサブ集約およびサブグループ化。 |
例
18 歳で数学で 100 点を取った人の数と、国語で 100 点を取った人の数をカウントします。
query = TermQuery('age', 18)
filter1 = TermQuery('math', 100)
filter2 = TermQuery('chinese', 100)
filters = [filter1, filter2]
group_by = GroupByFilter(filters)
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
i = 0
for item in group_by_result.items:
print(" filter: %s=%s, count: %d" % (str(filters[i].field_name), str(filters[i].column_value), item.row_count))
i += 1ヒストグラム集約
指定された数値間隔に基づいてクエリ結果をグループ化します。同じ間隔に収まるフィールド値を持つ行は同じグループに配置されます。応答では、各間隔とそれに対応するドキュメント数が返されます。
パラメーター
パラメーター | 説明 |
name | 集約のカスタム名。結果を取得するために使用されます。 |
field | 集約に使用されるフィールド。フィールドのデータの型は Long または Double である必要があります。 |
interval | 集約の間隔。 |
field_range[min,max] | 集約の範囲。このパラメーターは |
min_doc_count | 結果に含めるためのグループの最小ドキュメント数。この値より少ないドキュメントを持つグループは省略されます。 |
missing_value | 指定されたフィールドがないドキュメントのデフォルト値。このパラメーターが設定されている場合、その値が集約で使用されます。それ以外の場合、フィールドがないドキュメントは無視されます。 |
例
query = TermQuery('product', '10010')
group_by = GroupByHistogram(field_name='latency', interval=100, field_range=FieldRange(0, 10000), missing_value=0)
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.ALL_FROM_INDEX))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" key: %s, value: %s" % (item.key, item.value))複合集約
複合集約は、SQL の GROUP BY column1, column2, ... 句と同様に、複数のフィールドに基づいてクエリ結果をグループ化します。フィールド値によるグループ化とは異なり、複合集約は複数のソースにまたがるグループ化を同時にサポートし、ページネーションを使用してすべてのグループ化された結果を取得できます。ソースには最大 32 のソースが許可されます。
Python SDK 6.4.4 以降は複合集約をサポートしています。
パラメーター
パラメーター | 説明 |
name | 異なる集約を区別し、対応する結果を取得するために使用される集約のカスタム名。デフォルト値は |
sources | ソースのリスト。 説明
|
size | 各応答で返すグループの数。これはオプションのパラメーターで、デフォルト値は 10、最大値は 2000 です。返すグループの数を正確に制御します。指定された値が最大値を超えると、サーバーはエラーを返します。このパラメーターは |
next_token | 次のトークン。最初のリクエストでは設定する必要はありません。後続のリクエストでは、前の応答の |
suggested_size | 推奨されるグループ数。これはオプションのパラメーターで、任意の正の整数または -1 を受け入れます。提案モードでは、指定された値が最大値 (2000) を超える場合、エラーを返さずに自動的に最大値に調整されます。値 -1 もデフォルトで最大値になります。これは、範囲外エラーをトリガーせずにできるだけ多くのデータを取得したいデータ探索やバッチ処理などのシナリオに適しています。このパラメーターは |
sub_aggs and sub_group_bys | グループ化されたデータに対してさらなる分析を行うサブ集約およびサブグループ化。 |
返された結果では、各グループの
keysは、ソースと 1 対 1 で対応する文字列のリストです。ソースに対応するフィールド値が空の場合、keysの対応する位置の値はNoneです。グループ数が多い場合は、
sizeまたはsuggested_sizeパラメーターを設定し、next_tokenを使用して結果をページ分割で取得し、一度に大量のデータが返されるのを避けることを推奨します。応答のnext_tokenがNoneの場合、すべてのグループ結果が取得されたことを示します。
例 1
18 歳の人々を score フィールドでグループ化し、各スコア値の行数を取得します。
query = TermQuery('age', 18)
# GroupByField をソースとして使用する場合、field_name と name パラメーターのみを指定する必要があります。size パラメーターは設定できません。
source = GroupByField('score', name='group_by_score')
group_by = GroupByComposite(sources=[source])
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.NONE))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
print("source_names: %s" % str(group_by_result.source_group_by_names))
for item in group_by_result.items:
print(" keys: %s, count: %d" % (str(item.keys), item.row_count))例 2
18 歳の人々を score と sex フィールドでグループ化し、各スコアと性別の組み合わせの行数を取得します。
query = TermQuery('age', 18)
source1 = GroupByField('score', name='group_by_score')
source2 = GroupByField('sex', name='group_by_sex')
group_by = GroupByComposite(sources=[source1, source2])
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.NONE))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
print("source_names: %s" % str(group_by_result.source_group_by_names))
for item in group_by_result.items:
# keys パラメーターは、ソースに順番に対応する文字列のリストです。フィールド値が空の場合、対応する要素は None です。
print(" keys: %s, count: %d" % (str(item.keys), item.row_count))例 3
next_token を使用して、すべてのグループ化された結果をページ分割で取得します。結果は score フィールドでグループ化され、一度に 2 つのグループを取得して、ページネーションですべての結果を取得できます。
query = TermQuery('age', 18)
source = GroupByField('score')
group_by = GroupByComposite(sources=[source], size=2)
# 初期リクエスト
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.NONE))
group_by_result = search_response.group_by_results[0]
all_items = list(group_by_result.items)
# next_token が None になるまでページ分割して残りの結果を取得します。
while group_by_result.next_token is not None:
group_by = GroupByComposite(sources=[source], size=2, next_token=group_by_result.next_token)
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.NONE))
group_by_result = search_response.group_by_results[0]
all_items.extend(group_by_result.items)
# すべてのグループ化された結果を出力します。
for item in all_items:
print("keys: %s, count: %d" % (str(item.keys), item.row_count))例 4
サブ集約を使用して、score フィールドでデータをグループ化し、各グループの score の最大値を計算できます。
query = TermQuery('age', 18)
source = GroupByField('score')
sub_agg = Max('score')
group_by = GroupByComposite(sources=[source], sub_aggs=[sub_agg])
search_response = client.search(table_name, index_name,
SearchQuery(query, limit=0, get_total_count=True, group_bys=[group_by]),
ColumnsToGet(return_type=ColumnReturnType.NONE))
for group_by_result in search_response.group_by_results:
print("name: %s" % group_by_result.name)
for item in group_by_result.items:
print(" keys: %s, count: %d" % (str(item.keys), item.row_count))
for sub_agg in item.sub_aggs:
print(" sub_agg: %s, value: %s" % (sub_agg.name, str(sub_agg.value)))