拙ブログに、「Elasticsearch aggs/aggregations flat」で検索して迷いこむ方がいらっしゃるようです。
「flat」というところから、もしかして?、と思いまして、あらためて Elasticsearch のAggregationのひとつのCompositeに入門してみましたので、せっかくお越しいただいた方の参考になるかもということで、ご紹介します。
確認した、Elasticsearchのバージョンは6.8です。
なお、このブログでComposite以外のAggregationを試した他の記事はこちらです。
Composite aggregationと他のaggsの違い(compositeの嬉しいこと:検索結果がflatな配列で戻る)
Composite aggregation以外の例を先にご紹介してから、対比でComposite aggregationのメリットをお伝えすることにします。
他の記事にも例示しましたが、ElasticsearchのAggregationは、バケットの組み合わせ・掛け合わせができます。
例えば、Compositeではない(おそらくもっとメジャーな普通の)Aggregationの例では、次のクエリで(もちろんインデックスの作り次第ですが)、 都道府県ごとの、該当カテゴリごとの飲食店数が得られます。
POST /飲食店インデックス/_search { "aggs": { "bk1": { "terms": { "field": "都道府県", "size": 50 }, "aggs": { "bk2": { "terms": { "field": "飲食カテゴリ", "size": 100 } } } } } }
このクエリでは、検索結果の表現方法が、都道府県が親で飲食カテゴリが子のJSONとなります。
例えば、次のようなイメージです。
{ bk1:{ buckets:[ { key:東京都, bk2:{ buckets:[ { key:ラーメン, doc_count: 1000 }, { key:フレンチ, doc_count: 500 } ] } }, ] } }
ここで、好みの範囲なのですが、上記の例であれば、次のような戻し方をしてくれると嬉しいな〜と思いませんか。 このような戻り値の形式、ある種のflat/フラットな表現で結果が得られると嬉しいなというのが、「Composite Aggregations」です。
{ buckets:[ { key1:東京都, key2:ラーメン, doc_count: 1000 }, { key1:東京都, key2:フレンチ, doc_count: 500 } ... ] }
Composite aggregationクエリの例
ということで、「Composite aggregation」の例です。
「compostite」プロパティで制御します。また、ポイントは「sources」の中です。 ちなみに、terms以外も、ヒストグラムなどいくつかの、集計の方法が指定できます。
GET /インデックス名/_search { "aggs": { "my_buckets": { "composite": { "sources": [ { "prefecture": { "terms": { "field": "集計対象のフィールド_都道府県"} } }, { "category": { "terms": { "field": "集計対象のフィールド_レストランカテゴリ" } } } /* ここに他にも条件を加えたければ追加可能 */ ], "size": 10000 } } } }
結果の例
先のクエリの戻りは次のようになります。
トップレベルのbucketsの中で、都道府県と飲食カテゴリの組み合わせの配列が得られますね。
{ "aggregations" : { "my_buckets" : { "buckets" : [ { "key" : { "prefecture" : "東京都", "category" : "焼き鳥" }, "doc_count" : 2181 }, { "key" : { "prefecture" : "東京都", "category" : "焼きとん", }, "doc_count" : 18 }, { "key" : { "prefecture" : "東京都", "category" : "焼きそば・焼きうどん", }, "doc_count" : 120 }, ... }
注意事項など
Compositeに限らず、Aggregationは重い処理なので、性能などや、sizeの指定件数等はよろしくお気をつけください。
それ以外では、他のAggregationにぶら下げる無印の「terms」と次のようなところが異なるところです。
1) 取得件数は、compositeプロパティの直下のsizeで指定できます。
2) 他のaggsでは可能な、doc_count順のソートができません。
3) termsは、keyの昇順・降順の並び指定が、orderパラメータで指定できます。 繰り返しますが、doc_count順のソートはできません。
aggregationsの無印のtermsとは少し違いますね。
参考:無印のterms Terms aggregation | Elasticsearch Guide [7.13] | Elastic
4) 上記の戻り値イメージでは割愛したのですが、戻り値のトップフィールドに「buckets」と同じ並びに、「after_key」というものがあります。 「after_key」には、buckets配列の最後のエントリと同じものが入っています。一見不思議な項目なのですが、検索結果が多い場合のページネーションの目印となります。 具体的には、この値を同じ条件のaggs-compositeクエリの「after」フィールドに指定してやることで、それ以降のエントリを取得することができます。
戻り値をフラットな形式にしてくれるとともに、1)、2)、3)のような挙動から察するに、他のAggregationに比べて、全パターンを取得したい/取得せざるを得ない要件において、ページネーションしながら使って良いよ、という方針かなと思いました。