ES|QL クエリの始め方

このガイドでは、ES|QLを使用してデータをクエリし、集計する方法を示します。

この入門ガイドは、elasticsearch-labs GitHub リポジトリの インタラクティブ Python ノートブック としても利用可能です。

前提条件

このガイドのクエリに従うには、自分のデプロイメントを設定するか、Elastic の公開 ES|QL デモ環境を使用できます。

まず、いくつかのサンプルデータを取り込みます。Kibana で、メインメニューを開き、Dev
Tools を選択します。次の 2 つのリクエストを実行します:

Python

  1. resp = client.indices.create(
  2. index="sample_data",
  3. mappings={
  4. "properties": {
  5. "client_ip": {
  6. "type": "ip"
  7. },
  8. "message": {
  9. "type": "keyword"
  10. }
  11. }
  12. },
  13. )
  14. print(resp)
  15. resp1 = client.bulk(
  16. index="sample_data",
  17. operations=[
  18. {
  19. "index": {}
  20. },
  21. {
  22. "@timestamp": "2023-10-23T12:15:03.360Z",
  23. "client_ip": "172.21.2.162",
  24. "message": "Connected to 10.1.0.3",
  25. "event_duration": 3450233
  26. },
  27. {
  28. "index": {}
  29. },
  30. {
  31. "@timestamp": "2023-10-23T12:27:28.948Z",
  32. "client_ip": "172.21.2.113",
  33. "message": "Connected to 10.1.0.2",
  34. "event_duration": 2764889
  35. },
  36. {
  37. "index": {}
  38. },
  39. {
  40. "@timestamp": "2023-10-23T13:33:34.937Z",
  41. "client_ip": "172.21.0.5",
  42. "message": "Disconnected",
  43. "event_duration": 1232382
  44. },
  45. {
  46. "index": {}
  47. },
  48. {
  49. "@timestamp": "2023-10-23T13:51:54.732Z",
  50. "client_ip": "172.21.3.15",
  51. "message": "Connection error",
  52. "event_duration": 725448
  53. },
  54. {
  55. "index": {}
  56. },
  57. {
  58. "@timestamp": "2023-10-23T13:52:55.015Z",
  59. "client_ip": "172.21.3.15",
  60. "message": "Connection error",
  61. "event_duration": 8268153
  62. },
  63. {
  64. "index": {}
  65. },
  66. {
  67. "@timestamp": "2023-10-23T13:53:55.832Z",
  68. "client_ip": "172.21.3.15",
  69. "message": "Connection error",
  70. "event_duration": 5033755
  71. },
  72. {
  73. "index": {}
  74. },
  75. {
  76. "@timestamp": "2023-10-23T13:55:01.543Z",
  77. "client_ip": "172.21.3.15",
  78. "message": "Connected to 10.1.0.1",
  79. "event_duration": 1756467
  80. }
  81. ],
  82. )
  83. print(resp1)

Ruby

  1. response = client.indices.create(
  2. index: 'sample_data',
  3. body: {
  4. mappings: {
  5. properties: {
  6. client_ip: {
  7. type: 'ip'
  8. },
  9. message: {
  10. type: 'keyword'
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response
  17. response = client.bulk(
  18. index: 'sample_data',
  19. body: [
  20. {
  21. index: {}
  22. },
  23. {
  24. "@timestamp": '2023-10-23T12:15:03.360Z',
  25. client_ip: '172.21.2.162',
  26. message: 'Connected to 10.1.0.3',
  27. event_duration: 3_450_233
  28. },
  29. {
  30. index: {}
  31. },
  32. {
  33. "@timestamp": '2023-10-23T12:27:28.948Z',
  34. client_ip: '172.21.2.113',
  35. message: 'Connected to 10.1.0.2',
  36. event_duration: 2_764_889
  37. },
  38. {
  39. index: {}
  40. },
  41. {
  42. "@timestamp": '2023-10-23T13:33:34.937Z',
  43. client_ip: '172.21.0.5',
  44. message: 'Disconnected',
  45. event_duration: 1_232_382
  46. },
  47. {
  48. index: {}
  49. },
  50. {
  51. "@timestamp": '2023-10-23T13:51:54.732Z',
  52. client_ip: '172.21.3.15',
  53. message: 'Connection error',
  54. event_duration: 725_448
  55. },
  56. {
  57. index: {}
  58. },
  59. {
  60. "@timestamp": '2023-10-23T13:52:55.015Z',
  61. client_ip: '172.21.3.15',
  62. message: 'Connection error',
  63. event_duration: 8_268_153
  64. },
  65. {
  66. index: {}
  67. },
  68. {
  69. "@timestamp": '2023-10-23T13:53:55.832Z',
  70. client_ip: '172.21.3.15',
  71. message: 'Connection error',
  72. event_duration: 5_033_755
  73. },
  74. {
  75. index: {}
  76. },
  77. {
  78. "@timestamp": '2023-10-23T13:55:01.543Z',
  79. client_ip: '172.21.3.15',
  80. message: 'Connected to 10.1.0.1',
  81. event_duration: 1_756_467
  82. }
  83. ]
  84. )
  85. puts response

Js

  1. const response = await client.indices.create({
  2. index: "sample_data",
  3. mappings: {
  4. properties: {
  5. client_ip: {
  6. type: "ip",
  7. },
  8. message: {
  9. type: "keyword",
  10. },
  11. },
  12. },
  13. });
  14. console.log(response);
  15. const response1 = await client.bulk({
  16. index: "sample_data",
  17. operations: [
  18. {
  19. index: {},
  20. },
  21. {
  22. "@timestamp": "2023-10-23T12:15:03.360Z",
  23. client_ip: "172.21.2.162",
  24. message: "Connected to 10.1.0.3",
  25. event_duration: 3450233,
  26. },
  27. {
  28. index: {},
  29. },
  30. {
  31. "@timestamp": "2023-10-23T12:27:28.948Z",
  32. client_ip: "172.21.2.113",
  33. message: "Connected to 10.1.0.2",
  34. event_duration: 2764889,
  35. },
  36. {
  37. index: {},
  38. },
  39. {
  40. "@timestamp": "2023-10-23T13:33:34.937Z",
  41. client_ip: "172.21.0.5",
  42. message: "Disconnected",
  43. event_duration: 1232382,
  44. },
  45. {
  46. index: {},
  47. },
  48. {
  49. "@timestamp": "2023-10-23T13:51:54.732Z",
  50. client_ip: "172.21.3.15",
  51. message: "Connection error",
  52. event_duration: 725448,
  53. },
  54. {
  55. index: {},
  56. },
  57. {
  58. "@timestamp": "2023-10-23T13:52:55.015Z",
  59. client_ip: "172.21.3.15",
  60. message: "Connection error",
  61. event_duration: 8268153,
  62. },
  63. {
  64. index: {},
  65. },
  66. {
  67. "@timestamp": "2023-10-23T13:53:55.832Z",
  68. client_ip: "172.21.3.15",
  69. message: "Connection error",
  70. event_duration: 5033755,
  71. },
  72. {
  73. index: {},
  74. },
  75. {
  76. "@timestamp": "2023-10-23T13:55:01.543Z",
  77. client_ip: "172.21.3.15",
  78. message: "Connected to 10.1.0.1",
  79. event_duration: 1756467,
  80. },
  81. ],
  82. });
  83. console.log(response1);

コンソール

  1. PUT sample_data
  2. {
  3. "mappings": {
  4. "properties": {
  5. "client_ip": {
  6. "type": "ip"
  7. },
  8. "message": {
  9. "type": "keyword"
  10. }
  11. }
  12. }
  13. }
  14. PUT sample_data/_bulk
  15. {"index": {}}
  16. {"@timestamp": "2023-10-23T12:15:03.360Z", "client_ip": "172.21.2.162", "message": "Connected to 10.1.0.3", "event_duration": 3450233}
  17. {"index": {}}
  18. {"@timestamp": "2023-10-23T12:27:28.948Z", "client_ip": "172.21.2.113", "message": "Connected to 10.1.0.2", "event_duration": 2764889}
  19. {"index": {}}
  20. {"@timestamp": "2023-10-23T13:33:34.937Z", "client_ip": "172.21.0.5", "message": "Disconnected", "event_duration": 1232382}
  21. {"index": {}}
  22. {"@timestamp": "2023-10-23T13:51:54.732Z", "client_ip": "172.21.3.15", "message": "Connection error", "event_duration": 725448}
  23. {"index": {}}
  24. {"@timestamp": "2023-10-23T13:52:55.015Z", "client_ip": "172.21.3.15", "message": "Connection error", "event_duration": 8268153}
  25. {"index": {}}
  26. {"@timestamp": "2023-10-23T13:53:55.832Z", "client_ip": "172.21.3.15", "message": "Connection error", "event_duration": 5033755}
  27. {"index": {}}
  28. {"@timestamp": "2023-10-23T13:55:01.543Z", "client_ip": "172.21.3.15", "message": "Connected to 10.1.0.1", "event_duration": 1756467}

このガイドで使用されるデータセットは、Elastic ES|QL 公開デモ環境に事前にロードされています。ela.st/ql を訪れて使用を開始してください。

ES|QL クエリの実行

Kibana では、Console または Discover を使用して ES|QL クエリを実行できます:

Console で ES|QL を始めるには、メインメニューを開き、Dev Tools を選択します。

ES|QL クエリ API リクエストの一般的な構造は次のとおりです:

テキスト

  1. POST /_query?format=txt
  2. {
  3. "query": """
  4. """
  5. }

実際の ES|QL クエリを 2 つの三重引用符の間に入力します。例えば:

テキスト

  1. POST /_query?format=txt
  2. {
  3. "query": """
  4. FROM sample_data
  5. """
  6. }

Discover で ES|QL を始めるには、メインメニューを開き、Discover を選択します。次に、データビュー メニューから Language: ES|QL を選択します。

esql data view menu

サンプルデータのタイムスタンプを含むように、時間フィルターを調整します(2023年10月23日)。

ES|QL モードに切り替えると、クエリバーにサンプルクエリが表示されます。このクエリをこの入門ガイドのクエリに置き換えることができます。

クエリの記述を容易にするために、オートコンプリートは可能なコマンドや関数の提案を提供します:

esql kibana auto complete

マルチラインクエリの記述を容易にするために、二重矢印ボタン (esql icon expand query bar) をクリックしてクエリバーを展開します:

esql expanded query bar

コンパクトなクエリバーに戻るには、エディタを最小化するボタン (esql icon minimize query bar) をクリックします。

最初の ES|QL クエリ

各 ES|QL クエリは、ソースコマンド で始まります。ソースコマンドは、通常、Elasticsearch からのデータを持つテーブルを生成します。

Elasticsearch からテーブルを生成するソースコマンド

FROM ソースコマンドは、データストリーム、インデックス、またはエイリアスからのドキュメントを持つテーブルを返します。結果のテーブルの各行は、1 つのドキュメントを表します。このクエリは、sample_data インデックスから最大 1000 ドキュメントを返します:

Esql

  1. FROM sample_data

各列はフィールドに対応し、そのフィールドの名前でアクセスできます。

ES|QL キーワードは大文字と小文字を区別しません。次のクエリは前のクエリと同じです:

Esql

  1. from sample_data

処理コマンド

ソースコマンドの後には、パイプ文字で区切られた 1 つ以上の 処理コマンド を続けることができます: |。処理コマンドは、行や列を追加、削除、または変更することによって入力テーブルを変更します。処理コマンドは、フィルタリング、プロジェクション、集計などを実行できます。

入力テーブルを変更する処理コマンド

例えば、LIMIT コマンドを使用して、返される行の数を最大 10,000 行に制限できます:

Esql

  1. FROM sample_data
  2. | LIMIT 3

可読性のために、各コマンドを別の行に置くことができます。ただし、必ずしもそうする必要はありません。次のクエリは前のクエリと同じです:

Esql

  1. FROM sample_data | LIMIT 3

テーブルのソート

入力テーブルをソートする処理コマンド

別の処理コマンドは、SORT コマンドです。デフォルトでは、FROM によって返される行には定義されたソート順序がありません。SORT コマンドを使用して、1 つ以上の列で行をソートします:

Esql

  1. FROM sample_data
  2. | SORT @timestamp DESC

データのクエリ

データをクエリするには、WHERE コマンドを使用します。例えば、5ms より長い期間のすべてのイベントを見つけるには:

Esql

  1. FROM sample_data
  2. | WHERE event_duration > 5000000

WHERE は、いくつかの 演算子 をサポートしています。例えば、LIKE を使用して、message 列に対してワイルドカードクエリを実行できます:

Esql

  1. FROM sample_data
  2. | WHERE message LIKE "Connected*"

さらなる処理コマンド

KEEPDROP など、列を保持または削除するための他の多くの処理コマンドがあります。ENRICH は、Elasticsearch のインデックスからデータを使用してテーブルを強化し、DISSECTGROK はデータを処理します。処理コマンド を参照して、すべての処理コマンドの概要を確認してください。

処理コマンドのチェーン

処理コマンドは、パイプ文字で区切ってチェーンできます: |。各処理コマンドは、前のコマンドの出力テーブルで動作します。クエリの結果は、最終的な処理コマンドによって生成されたテーブルです。

処理コマンドはチェーンできます

次の例では、最初に @timestamp でテーブルをソートし、次に結果セットを 3 行に制限します:

Esql

  1. FROM sample_data
  2. | SORT @timestamp DESC
  3. | LIMIT 3

処理コマンドの順序は重要です。最初に結果セットを 3 行に制限してから、その 3 行をソートすると、この例とは異なる結果が返される可能性が高いです。この例では、ソートが制限の前に行われます。

値の計算

EVAL コマンドを使用して、計算された値を持つ列をテーブルに追加します。例えば、次のクエリは duration_ms 列を追加します。この列の値は、event_duration を 1,000,000 で割ることによって計算されます。言い換えれば、event_duration はナノ秒からミリ秒に変換されます。

Esql

  1. FROM sample_data
  2. | EVAL duration_ms = event_duration/1000000.0

EVAL は、いくつかの 関数 をサポートしています。例えば、指定された桁数で最も近い数に丸めるには、ROUND 関数を使用します:

Esql

  1. FROM sample_data
  2. | EVAL duration_ms = ROUND(event_duration/1000000.0, 1)

統計の計算

ES|QL は、データをクエリするだけでなく、データを集計するためにも使用できます。STATS ... BY コマンドを使用して統計を計算します。例えば、中央値の期間:

Esql

  1. FROM sample_data
  2. | STATS median_duration = MEDIAN(event_duration)

1 つのコマンドで複数の統計を計算できます:

Esql

  1. FROM sample_data
  2. | STATS median_duration = MEDIAN(event_duration), max_duration = MAX(event_duration)

BY を使用して、計算された統計を 1 つ以上の列でグループ化します。例えば、クライアント IP ごとの中央値の期間を計算するには:

Esql

  1. FROM sample_data
  2. | STATS median_duration = MEDIAN(event_duration) BY client_ip

列へのアクセス

列には、その名前でアクセスできます。名前に特殊文字が含まれている場合は、バックティックで引用する必要があります (` )。

EVAL または STATS によって作成された列に明示的な名前を付けることはオプションです。名前を提供しない場合、新しい列の名前は関数式と等しくなります。例えば:

Esql

  1. FROM sample_data
  2. | EVAL event_duration/1000000.0

このクエリでは、EVALevent_duration/1000000.0 という名前の新しい列を追加します。名前に特殊文字が含まれているため、この列にアクセスするには、バックティックで引用します:

Esql

  1. FROM sample_data
  2. | EVAL event_duration/1000000.0
  3. | STATS MEDIAN(`event_duration/1000000.0`)

ヒストグラムの作成

時間の経過に伴う統計を追跡するために、ES|QL は BUCKET 関数を使用してヒストグラムを作成できます。BUCKET は、人間に優しいバケットサイズを作成し、各行に対して、その行が属する結果のバケットに対応する値を返します。

BUCKET と組み合わせてヒストグラムを作成します。例えば、時間ごとのイベント数をカウントするには:

Esql

  1. FROM sample_data
  2. | STATS c = COUNT(*) BY bucket = BUCKET(@timestamp, 24, "2023-10-23T00:00:00Z", "2023-10-23T23:59:59Z")

または、時間ごとの中央値の期間:

Esql

  1. FROM sample_data
  2. | KEEP @timestamp, event_duration
  3. | STATS median_duration = MEDIAN(event_duration) BY bucket = BUCKET(@timestamp, 24, "2023-10-23T00:00:00Z", "2023-10-23T23:59:59Z")

ES|QL クエリの始め方

このガイドでは、ES|QLを使用してデータをクエリし、集計する方法を示します。

この入門ガイドは、elasticsearch-labs GitHub リポジトリの インタラクティブ Python ノートブック としても利用可能です。

Python

  1. resp = client.indices.create(
  2. index="clientips",
  3. mappings={
  4. "properties": {
  5. "client_ip": {
  6. "type": "keyword"
  7. },
  8. "env": {
  9. "type": "keyword"
  10. }
  11. }
  12. },
  13. )
  14. print(resp)
  15. resp1 = client.bulk(
  16. index="clientips",
  17. operations=[
  18. {
  19. "index": {}
  20. },
  21. {
  22. "client_ip": "172.21.0.5",
  23. "env": "Development"
  24. },
  25. {
  26. "index": {}
  27. },
  28. {
  29. "client_ip": "172.21.2.113",
  30. "env": "QA"
  31. },
  32. {
  33. "index": {}
  34. },
  35. {
  36. "client_ip": "172.21.2.162",
  37. "env": "QA"
  38. },
  39. {
  40. "index": {}
  41. },
  42. {
  43. "client_ip": "172.21.3.15",
  44. "env": "Production"
  45. },
  46. {
  47. "index": {}
  48. },
  49. {
  50. "client_ip": "172.21.3.16",
  51. "env": "Production"
  52. }
  53. ],
  54. )
  55. print(resp1)
  56. resp2 = client.enrich.put_policy(
  57. name="clientip_policy",
  58. match={
  59. "indices": "clientips",
  60. "match_field": "client_ip",
  61. "enrich_fields": [
  62. "env"
  63. ]
  64. },
  65. )
  66. print(resp2)
  67. resp3 = client.enrich.execute_policy(
  68. name="clientip_policy",
  69. wait_for_completion=False,
  70. )
  71. print(resp3)

Ruby

  1. response = client.indices.create(
  2. index: 'clientips',
  3. body: {
  4. mappings: {
  5. properties: {
  6. client_ip: {
  7. type: 'keyword'
  8. },
  9. env: {
  10. type: 'keyword'
  11. }
  12. }
  13. }
  14. }
  15. )
  16. puts response
  17. response = client.bulk(
  18. index: 'clientips',
  19. body: [
  20. {
  21. index: {}
  22. },
  23. {
  24. client_ip: '172.21.0.5',
  25. env: 'Development'
  26. },
  27. {
  28. index: {}
  29. },
  30. {
  31. client_ip: '172.21.2.113',
  32. env: 'QA'
  33. },
  34. {
  35. index: {}
  36. },
  37. {
  38. client_ip: '172.21.2.162',
  39. env: 'QA'
  40. },
  41. {
  42. index: {}
  43. },
  44. {
  45. client_ip: '172.21.3.15',
  46. env: 'Production'
  47. },
  48. {
  49. index: {}
  50. },
  51. {
  52. client_ip: '172.21.3.16',
  53. env: 'Production'
  54. }
  55. ]
  56. )
  57. puts response
  58. response = client.enrich.put_policy(
  59. name: 'clientip_policy',
  60. body: {
  61. match: {
  62. indices: 'clientips',
  63. match_field: 'client_ip',
  64. enrich_fields: [
  65. 'env'
  66. ]
  67. }
  68. }
  69. )
  70. puts response
  71. response = client.enrich.execute_policy(
  72. name: 'clientip_policy',
  73. wait_for_completion: false
  74. )
  75. puts response

Js

  1. const response = await client.indices.create({
  2. index: "clientips",
  3. mappings: {
  4. properties: {
  5. client_ip: {
  6. type: "keyword",
  7. },
  8. env: {
  9. type: "keyword",
  10. },
  11. },
  12. },
  13. });
  14. console.log(response);
  15. const response1 = await client.bulk({
  16. index: "clientips",
  17. operations: [
  18. {
  19. index: {},
  20. },
  21. {
  22. client_ip: "172.21.0.5",
  23. env: "Development",
  24. },
  25. {
  26. index: {},
  27. },
  28. {
  29. client_ip: "172.21.2.113",
  30. env: "QA",
  31. },
  32. {
  33. index: {},
  34. },
  35. {
  36. client_ip: "172.21.2.162",
  37. env: "QA",
  38. },
  39. {
  40. index: {},
  41. },
  42. {
  43. client_ip: "172.21.3.15",
  44. env: "Production",
  45. },
  46. {
  47. index: {},
  48. },
  49. {
  50. client_ip: "172.21.3.16",
  51. env: "Production",
  52. },
  53. ],
  54. });
  55. console.log(response1);
  56. const response2 = await client.enrich.putPolicy({
  57. name: "clientip_policy",
  58. match: {
  59. indices: "clientips",
  60. match_field: "client_ip",
  61. enrich_fields: ["env"],
  62. },
  63. });
  64. console.log(response2);
  65. const response3 = await client.enrich.executePolicy({
  66. name: "clientip_policy",
  67. wait_for_completion: "false",
  68. });
  69. console.log(response3);

コンソール

  1. PUT clientips
  2. {
  3. "mappings": {
  4. "properties": {
  5. "client_ip": {
  6. "type": "keyword"
  7. },
  8. "env": {
  9. "type": "keyword"
  10. }
  11. }
  12. }
  13. }
  14. PUT clientips/_bulk
  15. { "index" : {}}
  16. { "client_ip": "172.21.0.5", "env": "Development" }
  17. { "index" : {}}
  18. { "client_ip": "172.21.2.113", "env": "QA" }
  19. { "index" : {}}
  20. { "client_ip": "172.21.2.162", "env": "QA" }
  21. { "index" : {}}
  22. { "client_ip": "172.21.3.15", "env": "Production" }
  23. { "index" : {}}
  24. { "client_ip": "172.21.3.16", "env": "Production" }
  25. PUT /_enrich/policy/clientip_policy
  26. {
  27. "match": {
  28. "indices": "clientips",
  29. "match_field": "client_ip",
  30. "enrich_fields": ["env"]
  31. }
  32. }
  33. PUT /_enrich/policy/clientip_policy/_execute?wait_for_completion=false

ela.st/ql のデモ環境では、clientip_policy という名前の強化ポリシーがすでに作成され、実行されています。このポリシーは、IP アドレスを環境(「Development」、「QA」、または「Production」)にリンクします。

ポリシーを作成して実行した後、ENRICH コマンドで使用できます:

Esql

  1. FROM sample_data
  2. | KEEP @timestamp, client_ip, event_duration
  3. | EVAL client_ip = TO_STRING(client_ip)
  4. | ENRICH clientip_policy ON client_ip WITH env

ENRICH コマンドによって追加された新しい env 列を、後続のコマンドで使用できます。例えば、環境ごとの中央値の期間を計算するには:

Esql

  1. FROM sample_data
  2. | KEEP @timestamp, client_ip, event_duration
  3. | EVAL client_ip = TO_STRING(client_ip)
  4. | ENRICH clientip_policy ON client_ip WITH env
  5. | STATS median_duration = MEDIAN(event_duration) BY env

ES|QL によるデータの強化についての詳細は、データの強化 を参照してください。

データの処理

データには、分析を容易にするために 構造化 したい非構造化文字列が含まれている場合があります。例えば、サンプルデータには次のようなログメッセージが含まれています:

テキスト

  1. "Connected to 10.1.0.3"

これらのメッセージから IP アドレスを抽出することで、どの IP が最も多くのクライアント接続を受け入れたかを判断できます。

クエリ時に非構造化文字列を構造化するには、ES|QL の DISSECT および GROK コマンドを使用できます。DISSECT は、区切り文字ベースのパターンを使用して文字列を分割します。GROK は同様に機能しますが、正規表現を使用します。これにより、GROK はより強力になりますが、一般的に遅くなります。

この場合、正規表現は必要ありません。なぜなら、message は単純だからです: 「Connected to 」の後にサーバー IP が続きます。この文字列に一致させるには、次の DISSECT コマンドを使用できます:

Esql

  1. FROM sample_data
  2. | DISSECT message "Connected to %{server_ip}"

これにより、このパターンに一致する message を持つ行に server_ip 列が追加されます。他の行の server_ip の値は null です。

DISSECT コマンドによって追加された新しい server_ip 列を、後続のコマンドで使用できます。例えば、各サーバーが受け入れた接続数を判断するには:

Esql

  1. FROM sample_data
  2. | WHERE STARTS_WITH(message, "Connected to")
  3. | DISSECT message "Connected to %{server_ip}"
  4. | STATS COUNT(*) BY server_ip

ES|QL によるデータ処理の詳細は、DISSECT と GROK を使用したデータ処理 を参照してください。

詳細を学ぶ

ES|QL について詳しく学ぶには、ES|QL リファレンス および ES|QL の使用 を参照してください。