集約
集約は、メトリック、統計、またはその他の分析としてデータを要約します。集約は、次のような質問に答えるのに役立ちます:
- 私のウェブサイトの平均読み込み時間はどれくらいですか?
- 取引量に基づいて、私の最も価値のある顧客は誰ですか?
- 私のネットワークで大きなファイルと見なされるのは何ですか?
- 各製品カテゴリには何製品がありますか?
Elasticsearchは、集約を3つのカテゴリに整理します:
- メトリック集約は、フィールド値から合計や平均などのメトリックを計算します。
- バケット集約は、フィールド値、範囲、またはその他の基準に基づいてドキュメントをバケット(ビンとも呼ばれる)にグループ化します。
- パイプライン集約は、ドキュメントやフィールドの代わりに他の集約から入力を受け取ります。
集約を実行する
集約は、検索の一部として、検索APIのaggs
パラメータを指定することで実行できます。次の検索は、my-field
に対して用語集約を実行します:
Python
resp = client.search(
index="my-index-000001",
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
}
}
集約結果は、レスポンスのaggregations
オブジェクトに含まれています:
コンソール-結果
{
"took": 78,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 5,
"relation": "eq"
},
"max_score": 1.0,
"hits": [...]
},
"aggregations": {
"my-agg-name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": []
}
}
}
my-agg-name 集約の結果。 |
集約のスコープを変更する
#### Python
``````python
resp = client.search(
index="my-index-000001",
query={
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
},
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
},
)
print(resp)
`
Ruby
response = client.search(
index: 'my-index-000001',
body: {
query: {
range: {
"@timestamp": {
gte: 'now-1d/d',
lt: 'now/d'
}
}
},
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
query: {
range: {
"@timestamp": {
gte: "now-1d/d",
lt: "now/d",
},
},
},
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"query": {
"range": {
"@timestamp": {
"gte": "now-1d/d",
"lt": "now/d"
}
}
},
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
}
}
集約結果のみを返す
デフォルトでは、集約を含む検索は、検索ヒットと集約結果の両方を返します。集約結果のみを返すには、size
を0
に設定します:
Python
resp = client.search(
index="my-index-000001",
size=0,
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
size: 0,
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
size: 0,
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"size": 0,
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
}
}
}
}
複数の集約を実行する
同じリクエストで複数の集約を指定できます:
Python
resp = client.search(
index="my-index-000001",
aggs={
"my-first-agg-name": {
"terms": {
"field": "my-field"
}
},
"my-second-agg-name": {
"avg": {
"field": "my-other-field"
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-first-agg-name": {
terms: {
field: 'my-field'
}
},
"my-second-agg-name": {
avg: {
field: 'my-other-field'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
aggs: {
"my-first-agg-name": {
terms: {
field: "my-field",
},
},
"my-second-agg-name": {
avg: {
field: "my-other-field",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"aggs": {
"my-first-agg-name": {
"terms": {
"field": "my-field"
}
},
"my-second-agg-name": {
"avg": {
"field": "my-other-field"
}
}
}
}
サブ集約を実行する
バケット集約は、バケットまたはメトリックのサブ集約をサポートします。たとえば、avgサブ集約を持つ用語集約は、各ドキュメントのバケットの平均値を計算します。サブ集約のネストに制限はありません。
Python
resp = client.search(
index="my-index-000001",
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
},
"aggs": {
"my-sub-agg-name": {
"avg": {
"field": "my-other-field"
}
}
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
},
aggregations: {
"my-sub-agg-name": {
avg: {
field: 'my-other-field'
}
}
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
aggs: {
"my-sub-agg-name": {
avg: {
field: "my-other-field",
},
},
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
},
"aggs": {
"my-sub-agg-name": {
"avg": {
"field": "my-other-field"
}
}
}
}
}
}
コンソール-結果
{
...
"aggregations": {
"my-agg-name": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "foo",
"doc_count": 5,
"my-sub-agg-name": {
"value": 75.0
}
}
]
}
}
}
親集約、my-agg-name の結果。 |
|
my-agg-name のサブ集約、my-sub-agg-name の結果。 |
カスタムメタデータを追加する
#### Python
``````python
resp = client.search(
index="my-index-000001",
aggs={
"my-agg-name": {
"terms": {
"field": "my-field"
},
"meta": {
"my-metadata-field": "foo"
}
}
},
)
print(resp)
`
Ruby
response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
"my-agg-name": {
terms: {
field: 'my-field'
},
meta: {
"my-metadata-field": 'foo'
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
aggs: {
"my-agg-name": {
terms: {
field: "my-field",
},
meta: {
"my-metadata-field": "foo",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search
{
"aggs": {
"my-agg-name": {
"terms": {
"field": "my-field"
},
"meta": {
"my-metadata-field": "foo"
}
}
}
}
コンソール-結果
{
...
"aggregations": {
"my-agg-name": {
"meta": {
"my-metadata-field": "foo"
},
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": []
}
}
}
集約タイプを返す
デフォルトでは、集約結果には集約の名前が含まれますが、そのタイプは含まれません。集約タイプを返すには、typed_keys
クエリパラメータを使用します。
Python
resp = client.search(
index="my-index-000001",
typed_keys=True,
aggs={
"my-agg-name": {
"histogram": {
"field": "my-field",
"interval": 1000
}
}
},
)
print(resp)
Ruby
response = client.search(
index: 'my-index-000001',
typed_keys: true,
body: {
aggregations: {
"my-agg-name": {
histogram: {
field: 'my-field',
interval: 1000
}
}
}
}
)
puts response
Js
const response = await client.search({
index: "my-index-000001",
typed_keys: "true",
aggs: {
"my-agg-name": {
histogram: {
field: "my-field",
interval: 1000,
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search?typed_keys
{
"aggs": {
"my-agg-name": {
"histogram": {
"field": "my-field",
"interval": 1000
}
}
}
}
レスポンスは、集約の名前の前に集約タイプを返します。
いくつかの集約は、リクエストのタイプとは異なる集約タイプを返します。たとえば、用語、重要な用語、およびパーセンタイル集約は、集約フィールドのデータタイプに応じて異なる集約タイプを返します。
コンソール-結果
{
...
"aggregations": {
"histogram#my-agg-name": {
"buckets": []
}
}
}
集約タイプ、histogram 、その後に# セパレーターと集約の名前、my-agg-name が続きます。 |
集約でスクリプトを使用する
フィールドが必要な集約と正確に一致しない場合は、ランタイムフィールドで集約する必要があります:
Python
resp = client.search(
index="my-index-000001",
size="0",
runtime_mappings={
"message.length": {
"type": "long",
"script": "emit(doc['message.keyword'].value.length())"
}
},
aggs={
"message_length": {
"histogram": {
"interval": 10,
"field": "message.length"
}
}
},
)
print(resp)
Js
const response = await client.search({
index: "my-index-000001",
size: 0,
runtime_mappings: {
"message.length": {
type: "long",
script: "emit(doc['message.keyword'].value.length())",
},
},
aggs: {
message_length: {
histogram: {
interval: 10,
field: "message.length",
},
},
},
});
console.log(response);
コンソール
GET /my-index-000001/_search?size=0
{
"runtime_mappings": {
"message.length": {
"type": "long",
"script": "emit(doc['message.keyword'].value.length())"
}
},
"aggs": {
"message_length": {
"histogram": {
"interval": 10,
"field": "message.length"
}
}
}
}
スクリプトはフィールド値を動的に計算するため、集約に少しオーバーヘッドが追加されます。計算にかかる時間に加えて、terms
やfilters
のような一部の集約は、ランタイムフィールドで最適化の一部を使用できません。ランタイムフィールドを使用する際のパフォーマンスコストは、集約によって異なります。
集約キャッシュ
より迅速なレスポンスのために、Elasticsearchは、頻繁に実行される集約の結果をシャードリクエストキャッシュにキャッシュします。キャッシュされた結果を取得するには、各検索に同じpreference
文字列を使用します。検索ヒットが必要ない場合は、size
を0
に設定してキャッシュを埋めるのを避けます。
Elasticsearchは、同じ優先文字列を持つ検索を同じシャードにルーティングします。検索間でシャードのデータが変更されない場合、シャードはキャッシュされた集約結果を返します。
長い値の制限
集約を実行する際、Elasticsearchはdouble
値を使用して数値データを保持および表現します。その結果、long
の数値が253
を超える集約は近似値になります。