ロールアップ検索

8.11.0で非推奨

ロールアップは将来のバージョンで削除されます。代わりにダウンサンプリングを使用してください。

標準のクエリDSLを使用してロールアップデータを検索することを可能にします。

リクエスト

GET <target>/_rollup_search

説明

ロールアップ検索エンドポイントが必要なのは、内部的にロールアップされたドキュメントが元のデータとは異なるドキュメント構造を利用しているためです。ロールアップ検索エンドポイントは、標準のクエリDSLをロールアップドキュメントに一致する形式に書き換え、応答を受け取って元のクエリに基づいてクライアントが期待する形式に再度書き換えます。

パスパラメータ

  • <target>
  • (必須、文字列) リクエストを制限するために使用されるデータストリームとインデックスのカンマ区切りリスト。ワイルドカード表現(*)がサポートされています。
    このターゲットには、ロールアップインデックスと非ロールアップインデックスの両方を含めることができます。
    <target>パラメータのルール:
    • 少なくとも1つのデータストリーム、インデックス、またはワイルドカード表現を指定する必要があります。このターゲットにはロールアップインデックスまたは非ロールアップインデックスを含めることができます。データストリームの場合、ストリームのバックインデックスは非ロールアップインデックスとしてのみ機能します。<target>パラメータを省略するか、_allを使用することは許可されていません。
    • 複数の非ロールアップインデックスを指定することができます。
    • 1つのロールアップインデックスのみを指定できます。複数指定した場合、例外が発生します。
    • ワイルドカード表現を使用できますが、複数のロールアップインデックスに一致する場合、例外が発生します。ただし、複数の非ロールアップインデックスまたはデータストリームに一致する表現を使用することはできます。

リクエストボディ

リクエストボディは、通常の検索APIの機能のサブセットをサポートしています。サポートされているのは:

利用できない機能:

  • size: ロールアップは事前集約データで機能するため、検索ヒットは返されず、サイズはゼロに設定するか完全に省略する必要があります。
  • highlightersuggestorspost_filterprofileexplain: これらも同様に許可されていません。

履歴のみの検索例

生データで満たされたsensor-1という名前のインデックスがあり、次の構成でロールアップジョブを作成したと想像してください:

Python

  1. resp = client.rollup.put_job(
  2. id="sensor",
  3. index_pattern="sensor-*",
  4. rollup_index="sensor_rollup",
  5. cron="*/30 * * * * ?",
  6. page_size=1000,
  7. groups={
  8. "date_histogram": {
  9. "field": "timestamp",
  10. "fixed_interval": "1h",
  11. "delay": "7d"
  12. },
  13. "terms": {
  14. "fields": [
  15. "node"
  16. ]
  17. }
  18. },
  19. metrics=[
  20. {
  21. "field": "temperature",
  22. "metrics": [
  23. "min",
  24. "max",
  25. "sum"
  26. ]
  27. },
  28. {
  29. "field": "voltage",
  30. "metrics": [
  31. "avg"
  32. ]
  33. }
  34. ],
  35. )
  36. print(resp)

Js

  1. const response = await client.rollup.putJob({
  2. id: "sensor",
  3. index_pattern: "sensor-*",
  4. rollup_index: "sensor_rollup",
  5. cron: "*/30 * * * * ?",
  6. page_size: 1000,
  7. groups: {
  8. date_histogram: {
  9. field: "timestamp",
  10. fixed_interval: "1h",
  11. delay: "7d",
  12. },
  13. terms: {
  14. fields: ["node"],
  15. },
  16. },
  17. metrics: [
  18. {
  19. field: "temperature",
  20. metrics: ["min", "max", "sum"],
  21. },
  22. {
  23. field: "voltage",
  24. metrics: ["avg"],
  25. },
  26. ],
  27. });
  28. console.log(response);

コンソール

  1. PUT _rollup/job/sensor
  2. {
  3. "index_pattern": "sensor-*",
  4. "rollup_index": "sensor_rollup",
  5. "cron": "*/30 * * * * ?",
  6. "page_size": 1000,
  7. "groups": {
  8. "date_histogram": {
  9. "field": "timestamp",
  10. "fixed_interval": "1h",
  11. "delay": "7d"
  12. },
  13. "terms": {
  14. "fields": [ "node" ]
  15. }
  16. },
  17. "metrics": [
  18. {
  19. "field": "temperature",
  20. "metrics": [ "min", "max", "sum" ]
  21. },
  22. {
  23. "field": "voltage",
  24. "metrics": [ "avg" ]
  25. }
  26. ]
  27. }

このコマンドはsensor-*パターンをロールアップし、結果をsensor_rollupに保存します。このロールアップデータを検索するには、_rollup_searchエンドポイントを使用する必要があります。ただし、ロールアップデータを検索するために通常のクエリDSLを使用できることに注意してください:

Python

  1. resp = client.rollup.rollup_search(
  2. index="sensor_rollup",
  3. size=0,
  4. aggregations={
  5. "max_temperature": {
  6. "max": {
  7. "field": "temperature"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.rollup.rollup_search(
  2. index: 'sensor_rollup',
  3. body: {
  4. size: 0,
  5. aggregations: {
  6. max_temperature: {
  7. max: {
  8. field: 'temperature'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.rollup.rollupSearch({
  2. index: "sensor_rollup",
  3. size: 0,
  4. aggregations: {
  5. max_temperature: {
  6. max: {
  7. field: "temperature",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

コンソール

  1. GET /sensor_rollup/_rollup_search
  2. {
  3. "size": 0,
  4. "aggregations": {
  5. "max_temperature": {
  6. "max": {
  7. "field": "temperature"
  8. }
  9. }
  10. }
  11. }

クエリはsensor_rollupデータをターゲットにしており、これはジョブで構成されたロールアップデータを含んでいます。max集約がtemperatureフィールドに使用され、次の応答が得られます:

コンソール-結果

  1. {
  2. "took" : 102,
  3. "timed_out" : false,
  4. "terminated_early" : false,
  5. "_shards" : ... ,
  6. "hits" : {
  7. "total" : {
  8. "value": 0,
  9. "relation": "eq"
  10. },
  11. "max_score" : 0.0,
  12. "hits" : [ ]
  13. },
  14. "aggregations" : {
  15. "max_temperature" : {
  16. "value" : 202.0
  17. }
  18. }
  19. }

応答は、通常のクエリ+集約から期待される通りであり、リクエストに関するメタデータ(took_shardsなど)、検索ヒット(ロールアップ検索では常に空)、および集約応答を提供します。

ロールアップ検索は、ロールアップジョブで構成された機能に制限されています。たとえば、avgtemperatureフィールドの構成されたメトリックの1つでなかったため、平均温度を計算することはできません。その検索を実行しようとすると:

Python

  1. resp = client.rollup.rollup_search(
  2. index="sensor_rollup",
  3. size=0,
  4. aggregations={
  5. "avg_temperature": {
  6. "avg": {
  7. "field": "temperature"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.rollup.rollup_search(
  2. index: 'sensor_rollup',
  3. body: {
  4. size: 0,
  5. aggregations: {
  6. avg_temperature: {
  7. avg: {
  8. field: 'temperature'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.rollup.rollupSearch({
  2. index: "sensor_rollup",
  3. size: 0,
  4. aggregations: {
  5. avg_temperature: {
  6. avg: {
  7. field: "temperature",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

コンソール

  1. GET sensor_rollup/_rollup_search
  2. {
  3. "size": 0,
  4. "aggregations": {
  5. "avg_temperature": {
  6. "avg": {
  7. "field": "temperature"
  8. }
  9. }
  10. }
  11. }

コンソール-結果

  1. {
  2. "error": {
  3. "root_cause": [
  4. {
  5. "type": "illegal_argument_exception",
  6. "reason": "There is not a rollup job that has a [avg] agg with name [avg_temperature] which also satisfies all requirements of query.",
  7. "stack_trace": ...
  8. }
  9. ],
  10. "type": "illegal_argument_exception",
  11. "reason": "There is not a rollup job that has a [avg] agg with name [avg_temperature] which also satisfies all requirements of query.",
  12. "stack_trace": ...
  13. },
  14. "status": 400
  15. }

履歴のロールアップデータと非ロールアップデータの両方を検索

ロールアップ検索APIは、”ライブ”非ロールアップデータと集約されたロールアップデータの両方を検索する機能を持っています。これは、URIにライブインデックスを追加することで実現されます:

Python

  1. resp = client.rollup.rollup_search(
  2. index="sensor-1,sensor_rollup",
  3. size=0,
  4. aggregations={
  5. "max_temperature": {
  6. "max": {
  7. "field": "temperature"
  8. }
  9. }
  10. },
  11. )
  12. print(resp)

Ruby

  1. response = client.rollup.rollup_search(
  2. index: 'sensor-1,sensor_rollup',
  3. body: {
  4. size: 0,
  5. aggregations: {
  6. max_temperature: {
  7. max: {
  8. field: 'temperature'
  9. }
  10. }
  11. }
  12. }
  13. )
  14. puts response

Js

  1. const response = await client.rollup.rollupSearch({
  2. index: "sensor-1,sensor_rollup",
  3. size: 0,
  4. aggregations: {
  5. max_temperature: {
  6. max: {
  7. field: "temperature",
  8. },
  9. },
  10. },
  11. });
  12. console.log(response);

コンソール

  1. GET sensor-1,sensor_rollup/_rollup_search
  2. {
  3. "size": 0,
  4. "aggregations": {
  5. "max_temperature": {
  6. "max": {
  7. "field": "temperature"
  8. }
  9. }
  10. }
  11. }
URIがsensor-1sensor_rollupを同時に検索することに注意してください

検索が実行されると、ロールアップ検索エンドポイントは2つのことを行います:

  • 1. 元のリクエストは非ロールアップインデックスに変更されずに送信されます。
  • 2. 元のリクエストの書き換え版がロールアップインデックスに送信されます。

2つの応答が受信されると、エンドポイントはロールアップ応答を書き換え、2つを統合します。統合プロセス中に、2つの応答間でバケットに重複がある場合、非ロールアップインデックスのバケットが使用されます。

上記のクエリに対する応答は、ロールアップインデックスと非ロールアップインデックスをまたいでいるにもかかわらず、期待通りのものになります:

コンソール-結果

  1. {
  2. "took" : 102,
  3. "timed_out" : false,
  4. "terminated_early" : false,
  5. "_shards" : ... ,
  6. "hits" : {
  7. "total" : {
  8. "value": 0,
  9. "relation": "eq"
  10. },
  11. "max_score" : 0.0,
  12. "hits" : [ ]
  13. },
  14. "aggregations" : {
  15. "max_temperature" : {
  16. "value" : 202.0
  17. }
  18. }
  19. }