ブログ

Elasticsearchで2つのインデックスを結合する方法

Elasticsearch で 2 つのインデックスを結合するための用語クエリ、Logstash elasticsearch フィルター、エンリッチ プロセッサ、ES|QL の使用方法を説明します。

Elasticsearch では、2 つのインデックスを結合することは、従来の SQL リレーショナル データベースほど簡単ではありません。ただし、Elasticsearch が提供する特定のテクニックと機能を使用すれば、同様の結果を得ることは可能です。

歴史的に、多くの人々は、異なるインデックスを結合するメカニズムとしてnestedフィールド タイプを使用してきました。しかし、クエリのコストが高く、Kibana、特にLensの視覚化のサポートが不完全であるため、制限がありました。

この記事では、Elasticsearch で 2 つのインデックスを結合するプロセスを詳しく説明し、次のアプローチに焦点を当てます。

  1. termsクエリの使用

  2. 取り込みパイプラインでenrichプロセッサを使用する

  3. Logstash elasticsearchフィルター プラグイン

  4. ES|QL ENRICH

  5. ES|QL LOOKUP JOIN

用語クエリの使用

用語クエリは、Elasticsearch で 2 つのインデックスを結合する最も効果的な方法の 1 つです。このクエリは、特定のフィールドに 1 つ以上の正確な用語を含むドキュメントを取得するために使用されます。ここでは、これを使用して 2 つのインデックスを結合する方法について説明します。

まず、最初のインデックスから必要なデータを取得する必要があります。これは、単純な GET リクエストを使用して_source属性から値を取得することで実行できます。

# Simple GET request
GET first_index/_search

最初のインデックスからデータを取得したら、それを使用して 2 番目のインデックスをクエリできます。これは、一致させるフィールドと値を指定するtermsクエリを使用して行われます。

次に例を示します。

GET second_index/_search
{
  "query": {
    "terms": {
      "field_in_second_index": ["value1_from_first_index", "value2_from_first_index"]
    }
  }
}

この例では、 field_in_second_index 、最初のインデックスの値と一致させる 2 番目のインデックスのフィールドです。value1_from_first_indexvalue2_from_first_index 、2 番目のインデックスで一致させる最初のインデックスの値です。

用語クエリは、用語ルックアップと呼ばれる手法を使用して、上記の 2 つの手順を 1 回のショットで実行するためのサポートも提供します。Elasticsearch は、別のインデックスから一致する値を透過的に取得します。たとえば、プレーヤーのリストを含むチーム インデックスがある場合:

PUT teams/_doc/team1
{
  "players":   ["john", "bill", "michael"]
}
PUT teams/_doc/team2
{
  "players":   ["aaron", "joe", "donald"]
}

以下に示すように、team1 でプレイしているすべての人々の人インデックスをクエリすることができます。

GET people/_search?pretty
{
  "query": {
    "terms": {
        "name" : {
            "index" : "teams",
            "id" : "team1",
            "path" : "players"
        }
    }
  }
}

上記の例では、Elasticsearchはチームインデックス内のID team1 を持つドキュメントからプレーヤー名を透過的に取得します(つまり、たとえば、「john」、「bill」、「michael」など) を検索し、名前フィールドにこれらの値のいずれかを含む人物インデックス内のすべてのドキュメントを検索します。

興味がある方のために、同等の SQL クエリは次のようになります。

SELECT p.* FROM people p
INNER JOIN teams t ON p.name = t.players

エンリッチプロセッサの使用

enrichプロセッサは、Elasticsearch 内の 2 つのインデックスを結合するために使用できるもう 1 つの強力なツールです。このプロセッサは、事前に定義されたエンリッチ インデックスからデータを追加することで、受信ドキュメントのデータをエンリッチします。

エンリッチ プロセッサを使用して 2 つのインデックスを結合する方法は次のとおりです。

1. まず、エンリッチポリシーを作成する必要があります。このポリシーは、エンリッチメントに使用するインデックス、一致させるフィールド、および受信ドキュメントのエンリッチメントに使用するフィールドを定義します。

次に例を示します。

PUT _enrich/policy/my_enrich_policy
{
  "match": {
    "indices": "first_index",
    "match_field": "field_in_first_index",
    "enrich_fields": ["field_to_enrich"]
  }
}

2. ポリシーが作成されたら、それを実行して、新しく作成されたポリシーからエンリッチ インデックスを作成する必要があります。

PUT _enrich/policy/my_enrich_policy/_execute

これにより、エンリッチメント中に使用される新しい非表示のエンリッチメント インデックスが構築されます。ソース インデックスのサイズによっては、この操作に時間がかかる場合があります。次のステップに進む前に、エンリッチポリシーが完全に構築されていることを確認してください。

3. エンリッチポリシーを構築したら、取り込みパイプラインでエンリッチプロセッサを使用して、受信ドキュメントのデータをエンリッチできます。

PUT _ingest/pipeline/my_pipeline
{
  "processors": [
    {
      "enrich": {
        "policy_name": "my_enrich_policy",
        "field": "field_in_second_index",
        "target_field": "enriched_field"
      }
    }
  ]
}

この例では、 field_in_second_index 、最初のインデックスのmatch_fieldと一致する必要がある 2 番目のインデックスのフィールドです。enriched_field 、最初のインデックスのenrich_fieldsから拡張されたデータを格納する、2 番目のインデックスの新しいフィールドです。

このアプローチの欠点の 1 つは、 first_indexのデータが変更された場合、エンリッチ ポリシーを再実行する必要があることです。エンリッチされたインデックスは、その構築元となったソース インデックスから自動的に更新または同期されることはありません。ただし、 first_indexが比較的安定している場合は、このアプローチはうまく機能します。

Logstash elasticsearch フィルター プラグイン

Logstash を使用する場合、上記のenrichプロセッサに似た別のオプションとして、 elasticsearchフィルター プラグインを使用して、指定されたクエリに基づいてイベントに関連フィールドを追加する方法があります。Logstash パイプラインの構成は、 my-pipeline.confなどの.confファイルに保存されます。

パイプラインがelasticsearch入力プラグインを使用して Elasticsearch からログを取得し、選択範囲を絞り込むクエリを実行しているとします。

input {
  # Read all documents from Elasticsearch matching the given query
  elasticsearch {
    hosts => "localhost"
    query => '{ "query": { "match": { "statuscode": 200 } }, "sort": [ "_doc" ] }'
  }
}

特定のインデックスからの情報を使用してこれらのメッセージを拡充したい場合は、 filterセクションのelasticsearchフィルター プラグインを使用してログを拡充できます。

filter {
   elasticsearch {
      hosts => ["localhost"]
      index => "index_name"
      query => "type:start AND operation:%{[opid]}"
      fields => { "@timestamp" => "started" }
   }
}

上記のコードは、インデックスindex_nameから、 typeが開始され、操作フィールドが指定されたopidと一致するドキュメントを検索し、 @timestampフィールドの値をstartedという名前の新しいフィールドにコピーします。

強化されたドキュメントは適切な出力ソース(この場合はelasticsearch出力プラグインを使用して Elasticsearch )に送信されます。

output {
    elasticsearch {
        hosts => "localhost"
        data_stream => "true"
    }
}

すでに Logstash を使用している場合、このオプションは、エンリッチメント ロジックを 1 か所に統合し、新しいイベントが発生したときに処理するのに役立ちます。ただし、そうでない場合は、ソリューションが複雑になり、実行および保守する必要がある別のコンポーネントが追加されることになります。

ES|QL エンリッチ

バージョン 8.14 で GA となったES|QLは、Elasticsearch でサポートされるパイプ クエリ言語であり、データのフィルタリング、変換、分析を可能にします。ENRICH 処理コマンドを使用すると、エンリッチ ポリシーを使用して既存のインデックスからデータを追加できます。

esql エンリッチ

出典: ES|QL 処理コマンド - ENRICH

元のエンリッチ プロセッサの例と同じポリシーmy_enrich_policyを使用すると、ES|QL の例は次のようになります。

FROM first_index
| WHERE field_in_first_index IS NOT NULL
| ENRICH my_enrich_policy

一致フィールドとエンリッチメント フィールド (この例ではそれぞれfield_in_first_indexfield_to_enrichをオーバーライドすることもできます。

FROM first_index
| WHERE field_in_first_index IS NOT NULL
| ENRICH my_enrich_policy ON another_field_in_first_index WITH different_field_to_enrich

明らかな制限は、最初にエンリッチポリシーを指定する必要があることですが、ES|QL では、必要に応じてフィールドを微調整できる柔軟性が提供されます。

ES|QL ルックアップ結合

Elasticsearch 8.18 では、Elasticsearch でインデックスを結合する新しい方法、つまりLOOKUP JOINコマンドが導入されました。このコマンドは、結合の右側にある新しいルックアップ インデックス モードを使用して、SQL スタイルの LEFT OUTER JOIN として動作します。

ES|QL ルックアップ結合

ソース: LOOKUP JOIN を使用して複数のインデックスからデータを結合する

前の例をもう一度見てみると、新しいクエリは次のようになります。ここで、 match_field first_indexsecond_index両方に存在する必要があります。

FROM first_index
| WHERE field_in_first_index IS NOT NULL
| LOOKUP JOIN second_index ON match_field

LOOKUP JOIN が他のアプローチよりも優れている点は、 enrichポリシーが不要であり、したがってポリシーの設定に関連する追加の処理も必要ないことです。これは、この記事で説明した他のアプローチとは異なり、頻繁に変更されるエンリッチメント データを扱う場合に役立ちます。

まとめ

結論として、Elasticsearch は従来の結合操作をサポートしていませんが、同様の結果を実現するために使用できるさまざまな機能を提供しています。具体的には、以下を使用して結合操作を実現する方法について説明しました。

  1. termsクエリ

  2. 取り込みパイプラインのenrichプロセッサ

  3. Logstash elasticsearchフィルター プラグイン

  4. ES|QL ENRICH

  5. ES|QL LOOKUP JOIN

これらの方法には限界があり、特定の要件とデータの性質に基づいて慎重に使用する必要があることに注意することが重要です。

関連記事

Elasticsearch の異なるバージョン間およびクラスター間でデータを移行する方法

Kofi Bartlett

Kibana に Elasticsearch クエリルール UI を導入

Jhon Guzmán

JavaScript で Elasticsearch を正しく使う方法、パート II

Jeffrey Rengifo

セマンティック検索の実装: Elasticsearch を使ったレシピ検索の構築

Andre Luiz

AWS MarketplaceでElasticsearchをデプロイする方法

Eduard Martin

最先端の検索体験を構築する準備はできましたか?

十分に高度な検索は 1 人の努力だけでは実現できません。Elasticsearch は、データ サイエンティスト、ML オペレーター、エンジニアなど、あなたと同じように検索に情熱を傾ける多くの人々によって支えられています。ぜひつながり、協力して、希望する結果が得られる魔法の検索エクスペリエンスを構築しましょう。

はじめましょう