この記事では、データ集約を正しく実装する方法、これが必要な理由、および多数の実用的な例を追加します。
ESでクエリをより面白くする方法に興味があり、反対側からの通常の検索を見ることに興味がある人のために、猫をお願いします。
前の記事では、ユーザーはより単純なトピックに関する記事とより複雑なトピックに関する記事に均等に分割されていたため、私はそれほど難しくないトピックを選択しましたが、比較的最近(ES)に追加された非常に興味深いトピックを選択しました(v1.0)。
集約モジュール
このモジュールはESでファセットに置き換わり、永続的な形式でファセットは廃止されたと見なされ、今後のリリースで削除されます。 集計がv1.0.0RC1に追加され、現在は1.2を超えていますが、ファセットの使用はお勧めしません。
なぜ作業ツールを変更する必要があったのですか?
おそらく、ユニットの主な機能はネストです。 リクエストの一般的な構文を示します。
"aggregations" : { "<aggregation_name>" : { "<aggregation_type>" : { <aggregation_body> } [,"aggregations" : { [<sub_aggregation>]+ } ]? } [,"<aggregation_name_2>" : { ... } ]* }
構造からわかるように、任意の数の集計が存在する可能性があり、各要素には深さの制限なしに要素を埋め込むことができます。
ネストを使用すると、非常に興味深い統計を取得できます(記事の最後の例)。
ユニットの種類
ユニットには多くのタイプがありますが、それらはすべて2つの主なタイプに組み合わせることができます。
-バケット(一般化)
理解を容易にするために、これはおなじみのすべてのGROUP BYツールと比較できます。 もちろん、これはかなり単純化された比較ですが、動作原理は似ています。 フィルターに基づくこのタイプは、特定の基準に従って文書を要約します;良い例は用語集約です。
-メトリック
これらは、特定のドキュメントセットの値を計算する集計です。 たとえば、 合計集計
理論の最初はこれで十分だと思います。このモジュールに関するより基本的な情報に興味がある人は誰でも、このリンクでそれを知ることができます。
簡単な例
自分の手ですべてを試してみたい人のために、このダンプを使用することをお勧めします
テストの構造とデータ
この美しい記事から無頓着にダンプ
curl -XPUT "http://localhost:9200/sports/" -d' { "mappings": { "athlete": { "properties": { "birthdate": { "type": "date", "format": "dateOptionalTime" }, "location": { "type": "geo_point" }, "name": { "type": "string" }, "rating": { "type": "integer" }, "sport": { "type": "string" } } } } }' curl -XPOST "http://localhost:9200/sports/_bulk" -d' {"index":{"_index":"sports","_type":"athlete"}} {"name":"Michael", "birthdate":"1989-10-1", "sport":"Baseball", "rating": ["5", "4"], "location":"46.22,-68.45"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Bob", "birthdate":"1989-11-2", "sport":"Baseball", "rating": ["3", "4"], "location":"45.21,-68.35"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Jim", "birthdate":"1988-10-3", "sport":"Baseball", "rating": ["3", "2"], "location":"45.16,-63.58" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Joe", "birthdate":"1992-5-20", "sport":"Baseball", "rating": ["4", "3"], "location":"45.22,-68.53"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Tim", "birthdate":"1992-2-28", "sport":"Baseball", "rating": ["3", "3"], "location":"46.22,-68.85"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Alfred", "birthdate":"1990-9-9", "sport":"Baseball", "rating": ["2", "2"], "location":"45.12,-68.35"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Jeff", "birthdate":"1990-4-1", "sport":"Baseball", "rating": ["2", "3"], "location":"46.12,-68.55"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Will", "birthdate":"1988-3-1", "sport":"Baseball", "rating": ["4", "4"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Mick", "birthdate":"1989-10-1", "sport":"Baseball", "rating": ["3", "4"], "location":"46.22,-68.45"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Pong", "birthdate":"1989-11-2", "sport":"Baseball", "rating": ["1", "3"], "location":"45.21,-68.35"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Ray", "birthdate":"1988-10-3", "sport":"Baseball", "rating": ["2", "2"], "location":"45.16,-63.58" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Ping", "birthdate":"1992-5-20", "sport":"Baseball", "rating": ["4", "3"], "location":"45.22,-68.53"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Duke", "birthdate":"1992-2-28", "sport":"Baseball", "rating": ["5", "2"], "location":"46.22,-68.85"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Hal", "birthdate":"1990-9-9", "sport":"Baseball", "rating": ["4", "2"], "location":"45.12,-68.35"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Charge", "birthdate":"1990-4-1", "sport":"Baseball", "rating": ["3", "2"], "location":"46.12,-68.55"} {"index":{"_index":"sports","_type":"athlete"}} {"name":"Barry", "birthdate":"1988-3-1", "sport":"Baseball", "rating": ["5", "2"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Bank", "birthdate":"1988-3-1", "sport":"Golf", "rating": ["6", "4"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Bingo", "birthdate":"1988-3-1", "sport":"Golf", "rating": ["10", "7"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"James", "birthdate":"1988-3-1", "sport":"Basketball", "rating": ["10", "8"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Wayne", "birthdate":"1988-3-1", "sport":"Hockey", "rating": ["10", "10"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Brady", "birthdate":"1988-3-1", "sport":"Football", "rating": ["10", "10"], "location":"46.25,-68.55" } {"index":{"_index":"sports","_type":"athlete"}} {"name":"Lewis", "birthdate":"1988-3-1", "sport":"Football", "rating": ["10", "10"], "location":"46.25,-68.55" }'
スポーツごとにアスリートをグループ化し、各スポーツに何人いるかを調べましょう。
curl -XPOST "http://localhost:9200/sports/athlete/_search?pretty" -d' { "size": 0, "aggregations": { "the_name": { "terms": { "field": "sport" } } } }'
ここでは、「スポーツ」フィールドでドキュメントをグループ化する「ターム」集計を使用します。
"size" : 0
(0は自動的にInteger.MAX_VALUEに置き換えられます)は、例外なくすべてのドキュメントが必要であることを意味します。この場合、速度は重要ではありませんが、より正確な結果にはより多くの時間が必要であることを考慮する必要があります
答えは:
{ ... "aggregations" : { "the_name" : { "buckets" : [ { "key" : "baseball", "doc_count" : 16 }, { "key" : "golf", "doc_count" : 2 }, { "key" : "basketball", "doc_count" : 1 }, { "key" : "football", "doc_count" : 1 }, { "key" : "hockey", "doc_count" : 1 } ] } } }
素晴らしい、野球選手が一番。
アスリートを評価の平均値で、大きいものから小さいものへと並べ替えましょう。
curl -XPOST "http://localhost:9200/sports/athlete/_search?pretty" -d' { "size": 0, "aggregations": { "the_name": { "terms": { "field": "name", "order": { "rating_avg": "desc" } }, "aggregations": { "rating_avg": { "avg": { "field": "rating" } } } } } }'
ここでは、ネストされた集合体とは何か、ドキュメントを可能な限り柔軟に選択するのにどのように役立つかを明確に見ることができます。
最初に、アスリートを名前でグループ化し、次に「評価」フィールドで「平均」集計で計算される「評価_平均」でソートする必要があることを示します。 ESが配列とどのようにエレガントに機能し(
"rating" : [10, 9]
)、平均値を簡単に計算するかに注目してください。
答えは:
{ ... "aggregations" : { "the_name" : { "buckets" : [ { "key" : "brady", "doc_count" : 1, "rating_avg" : { "value" : 10.0 } }, { "key" : "wayne", "doc_count" : 1, "rating_avg" : { "value" : 10.0 } }, { "key" : "james", "doc_count" : 1, "rating_avg" : { "value" : 9.0 } }, { "key" : "bingo", "doc_count" : 1, "rating_avg" : { "value" : 8.5 } }, ... {} ... { "key" : "duke", "doc_count" : 1, "rating_avg" : { "value" : 3.5 } }, { "key" : "bob", "doc_count" : 1, "rating_avg" : { "value" : 3.5 } } ] } } }
集計のもう1つの優れた機能は、
"script"
使用です。 例:
curl -XPOST "http://localhost:9200/sports/athlete/_search?pretty" -d' { "size": 0, "aggregations": { "age_ranges": { "range": { "script": "DateTime.now().year - doc[\"birthdate\"].date.year", "ranges": [ { "from": 22, "to": 25 } ] } } } }'
バージョン1.2.0以降、スクリプトの実行はデフォルトで無効になっています。 ユーザーがESに直接アクセスできない場合は 、 有効にすることができます(そうすることを望みます。そうでない場合は、データのセキュリティのためにこのアクセスをすぐに閉じることをお勧めします)。
すべての栄光またはより複雑なものの集合
ポイント
"46.12,-68.55"
から半径20マイル以内にいるすべてのアスリートを見つけましょう
スポーツの種類ごとにグループ化し、このスポーツのアスリートのランキングに関する詳細な統計を表示します。
良さそうですが、ここに例を示します。
curl -XPOST "http://localhost:9200/sports/athlete/_search?pretty" -d' { "size": 0, "aggregations": { "baseball_player_ring": { "geo_distance": { "field": "location", "origin": "46.12,-68.55", "unit": "mi", "ranges": [ { "from": 0, "to": 20 } ] }, "aggregations": { "sport": { "terms": { "field": "sport" }, "aggregations": { "rating_stats": { "stats": { "field": "rating" } } } } } } } } }'
答えは:
{ ... "aggregations" : { "baseball_player_ring" : { "buckets" : [ { "key" : "*-20.0", "from" : 0.0, "to" : 20.0, "doc_count" : 13, "sport" : { "buckets" : [ { "key" : "baseball", "doc_count" : 8, "rating_stats" : { "count" : 14, "min" : 2.0, "max" : 5.0, "avg" : 3.357142857142857, "sum" : 47.0 } }, { "key" : "golf", "doc_count" : 2, "rating_stats" : { "count" : 4, "min" : 4.0, "max" : 10.0, "avg" : 6.75, "sum" : 27.0 } }, { "key" : "basketball", "doc_count" : 1, "rating_stats" : { "count" : 2, "min" : 8.0, "max" : 10.0, "avg" : 9.0, "sum" : 18.0 } }, { "key" : "football", "doc_count" : 1, "rating_stats" : { "count" : 1, "min" : 10.0, "max" : 10.0, "avg" : 10.0, "sum" : 10.0 } }, { "key" : "hockey", "doc_count" : 1, "rating_stats" : { "count" : 1, "min" : 10.0, "max" : 10.0, "avg" : 10.0, "sum" : 10.0 } } ] } } ] } } }
おわりに
この素晴らしいモジュールの一般的な機能を伝えることができたと思います。 このトピックに興味のある方は、 このリンクでフィルターのリスト全体を読むことをお勧めします。
このトピックに関する有益なコメントや追加を歓迎します。
ESに関する以前の記事-ElasticSearchを読んで、他の方法で検索することもできます。 浸透API
そして、記事の最後にある投票に参加してください。
-目標の達成