AlloyDB for PostgreSQL から Elasticsearch データにアクセスする

AlloyDB for PostgreSQL で外部データ ラッパー(FDW)と外部テーブルを作成して、 Elasticsearchに保存されているデータにアクセスして検索します。

制限事項

AlloyDB を Elasticsearch に接続する前に、次の制限事項を確認してください。

  • Elasticsearch の統合は、PostgreSQL のメジャー バージョン 17 以降でのみ使用できます。

  • AlloyDB は Elasticsearch データを読み取りますが、書き込みは行いません。

  • AlloyDB と Elasticsearch 間のデータ同期は、お客様の責任で行ってください。

  • geo_point などの特殊な Elasticsearch タイプは対象外です。サポートされているデータ型の完全なリストについては、 サポートされているデータ型をご覧ください。

始める前に

始める前に、次の操作が完了していることを確認してください。

Elasticsearch API キーを Secret Manager に保存する

AlloyDB は、Elasticsearch API キーを Secret Manager に保存して読み取ります。Secret Manager の使用方法の詳細については、 Secret Manager を使用してシークレットを作成してアクセスするをご覧ください。

AlloyDB サービス アカウントにシークレットの読み取り権限を付与してください。詳細については、 Secret Manager を使用してシークレットを作成してアクセスするをご覧ください。

external_search_fdw 拡張機能を有効にして構成する

Elasticsearch との統合を開始するには、次の 手順に沿って external_search_fdw AlloyDB 拡張機能を有効にして構成します。

  1. external_search_fdw 拡張機能を有効にします。

    CREATE EXTENSION external_search_fdw;
    
  2. 外部データサーバーを介して Elasticsearch クラスタへのアクセスを構成します。

    CREATE SERVER ELASTICSEARCH_SERVER_NAME
    FOREIGN DATA WRAPPER external_search_fdw
    OPTIONS (server 'ELASTICSEARCH_SERVER_HOST_PORT',
             search_provider 'elastic',
             auth_mode 'secret_manager',
             auth_method 'AUTH_METHOD',
             secret_path 'SECRET_PATH',
             max_deadline_ms 'MAX_DEADLINE',
             pagination_num_results 'PAGINATION_NUM_RESULTS',
             pagination_context_timeout_ms 'PAGINATION_CONTEXT_TIMEOUT');
    

    次の変数を置き換えます。

    • ELASTICSEARCH_SERVER_NAME: 外部データサーバーの名前。例: my-elasticsearch-server

    • ELASTICSEARCH_SERVER_HOST_PORT: Elasticsearch クラスタの公開 URL。例: https://node1.elastic.test.com:9200

    • AUTH_METHOD: 使用する認証のタイプ。次のオプションから選択できます。

    • SECRET_PATH: Elasticsearch 認証情報への Secret Manager パス。例: projects/123456789012/secrets/apikey/versions/1123456789012 は実際の Google Cloud プロジェクト ID を表します。

    • (省略可)MAX_DEADLINE: AlloyDB が Elasticsearch からのレスポンスを待機する最大時間(ミリ秒単位)。この値は、AlloyDB インスタンスと Elasticsearch インスタンスの場所に基づいて設定する必要があります。デフォルト値は 10000 です。

    • (省略可)PAGINATION_NUM_RESULTS: Elasticsearch からバッチごとに取得する結果の最大数。より多くの結果がリクエストされた場合、AlloyDB はこのサイズの複数のバッチで結果を取得します。デフォルト値は 32 です。

    • (省略可)PAGINATION_CONTEXT_TIMEOUT: Elasticsearch がページネーション リクエスト コンテキストをアクティブに保つ時間(ミリ秒単位)。デフォルト値は 30000 です。

  3. Elasticsearch サーバーの PostgreSQL ユーザー マッピングを定義します。PostgreSQL FDW が機能するには、このユーザー マッピングが必要です。 AlloyDB は REST 認証ヘッダーを使用して認証します。

    CREATE USER MAPPING FOR CURRENT_USER
           SERVER ELASTICSEARCH_SERVER_NAME;
    
  4. 外部データテーブルを介して Elasticsearch データのスキーマを構成します。

    CREATE FOREIGN TABLE ELASTICSEARCH_FD_TABLE(
        metadata external_search_fdw_schema.OpaqueMetadata,
        ELASTICSEARCH_FIELDS)
           SERVER ELASTICSEARCH_SERVER_NAME
           OPTIONS(remote_table_name 'ELASTICSEARCH_INDEX_NAME');
    

    次の新しい変数を置き換えます。

    • ELASTICSEARCH_FD_TABLE: Elasticsearch テーブルを表す外部データテーブルの名前。 例: my-fd-elasticsearch-table

    • ELASTICSEARCH_FIELDS: 次の形式の Elasticsearch フィールド スキーマ定義のカンマ区切りのリスト: elasticsearch_field_name PG_DATA_TYPE。例: elasticsearch_boolean_field_name BOOLEAN, elasticsearch_double_field_name DOUBLE PRECISIONremote_field_name オプションが追加されていない限り、これらのフィールドは Elasticsearch のフィールド名と一致する必要があります。例: elasticsearch_foo OPTIONS (remote_field_name 'elasticsearch_FOO')

      AlloyDB に定義できる Elasticsearch データ型のリストについては、 サポートされているデータ型をご覧ください。

    • ELASTICSEARCH_INDEX_NAME: Elasticsearch インデックスの名前。例: my-elasticsearch-index

サポートされるデータタイプ

AlloyDB は、次の Elasticsearch データ型をサポートしています。

データ型 PostgreSQL タイプ
alias alias が参照しているフィールドの PostgreSQL タイプ
binary bytea
boolean BOOLEAN

byte

short

SMALLINT
date TIMESTAMPTZ

double

scaled_float

DOUBLE PRECISION

float

half_float

REAL
integer INTEGER
long BIGINT

object

flattened

jsonb

text

annotated_text

keyword

constant_keyword

wildcard

TEXT
unsigned_long NUMERIC

Elasticsearch データのクエリ

AlloyDB は SQL クエリを受け取り、Elasticsearch REST API クエリに変換します。この変換中、AlloyDB は、SQL クエリの LIMIT など、クエリの ID を変更せずに、可能な限り多くのクエリ ロジックをプッシュダウンしようとします。ただし、特定の Elasticsearch フィールドをプッシュダウンしないように指定する場合や、クエリ ロジックをプッシュダウンできない場合があります。たとえば、LIKE などのテキスト一致演算子はプッシュダウンできません。プッシュダウンできるものとできないものの例については、プッシュダウンの例をご覧ください。

LIMITpagination_num_results より大きい場合、または LIMIT が指定されていないかプッシュダウンできない場合、AlloyDB はリソースを大量に消費する可能性がある Scroll API を使用します。

Scroll API はリソースを大量に消費する可能性があるため、EXPLAIN VERBOSE を使用してクエリを調べ、使用されている API を確認することをおすすめします。Scroll API の使用を制限して LIMIT を使用すると、パフォーマンスが向上します。

Elasticsearch データをクエリするには、次のオプションがあります。

  • 標準 SQL クエリ
  • クエリ DSL
  • ハイブリッド検索

標準 SQL クエリ

標準 SQL クエリは、Elasticsearch の Lucene 構文を使用して記述できます。

標準 SQL クエリを実行するには、次のクエリ例をご覧ください。

SELECT id, body
FROM ELASTICSEARCH_FD_TABLE
WHERE FILTER
ORDER BY metadata <@> 'QUERY';

次の変数を置き換えます。

  • ELASTICSEARCH_FD_TABLE: Elasticsearch テーブルを表す外部データテーブルの名前。例: my-fd-elasticsearch-table

  • (省略可)FILTER: Elasticsearch クエリに適用するフィルタ。例: AND qubits < 105

  • QUERY: Elasticsearch に送信するクエリ。クエリの例については、次のリストをご覧ください。

    • body:quantum body:computing
    • body:(quantum computing)
    • body:(quantum AND computing)
    • body:"quantum computing"
    • body:"quantum computing" AND qubits:[* TO 105}

クエリ DSL

クエリ DSL は、高度なユースケースにおすすめの、Elasticsearch のフル機能の JSON スタイルのクエリ言語です。クエリ DSL を使用すると、SQL クエリ構文では表現できない複雑な検索、フィルタリング、集計を実行できます。

クエリ DSL を使用してクエリを実行するには、次のクエリ例をご覧ください。

SELECT id, body
FROM ELASTICSEARCH_FD_TABLE
ORDER BY
  metadata <@> $${
    "query": {
      "bool": {
        "must": [
          {
            "query_string": {
              "query" : "QUERY"
            }
          }
        ],
        "filter": [
          {
            "range": { 
              "id": { 
                "lt": "10"
              }
            }
          }
        ]
      }
    },
    "sort": [
      {
        "id": {
          "order": "desc"
        }
      }
    ]
  }$$
LIMIT 1;

次の変数を置き換えます。

  • ELASTICSEARCH_FD_TABLE: Elasticsearch テーブルを表す外部データテーブルの名前。例: my-fd-elasticsearch-table

  • QUERY: Elasticsearch に送信するクエリ。例: "elasticsearch_field_name:\"quantum computing\" OR int_field:[* TO 3]".

クエリ DSL の場合、伝播する必要があるのは queryfiltersort 式のみです。

Elasticsearch データに対して ハイブリッド検索 を実行するには、次の検索例をご覧ください。

SELECT *
FROM
  ai.hybrid_search(
    ARRAY[
      '{"limit": LIMIT,
        "data_type": "external_search_fdw",
        "weight": WEIGHT,
        "table_name": "ELASTICSEARCH_FD_TABLE",
        "key_column": "DOCUMENT_ID_COLUMN_NAME",
        "query_text_input": QUERY}'::jsonb],
    NULL::TEXT,
    'RRF',
    FALSE)
ORDER BY score DESC;

次の変数を置き換えます。

  • LIMIT: 返す結果の数。例: 3

  • WEIGHT: この検索エントリが Reciprocal Rank Fusion(RRF)全体に与える影響。

  • ELASTICSEARCH_FD_TABLE: Elasticsearch テーブルを表す外部データテーブルの名前。例: my-fd-elasticsearch-table

  • DOCUMENT_ID_COLUMN_NAME: ドキュメント ID 列の名前。

  • QUERY: Elasticsearch に送信するクエリ。たとえば、 "elasticsearch_field_name:\"quantum computing\"" は、elasticsearch_field_name フィールドで "quantum computing" というフレーズを検索します。サポートされているデータ型 で説明されているすべてのクエリタイプをクエリで使用できます。

ハイブリッド検索で使用できるパラメータの詳細については、 ハイブリッド検索関数のパラメータをご覧ください。

プッシュダウンの例

クエリをより効率的にするために、AlloyDB はクエリの次の側面を Elasticsearch への API 呼び出しに直接プッシュダウンしようとします。

  • SELECT フィールド
  • WHERE フィルタ
  • ORDER BY 並べ替え
  • LIMIT

AlloyDB がプッシュダウンできる側面とできない側面を示すクエリの例については、次の表をご覧ください。

クエリの形式 クエリの例 プッシュダウンされたクエリ要素
フィルタなしのクエリ
SELECT id, body
FROM elasticsearch_table
ORDER BY metadata <@> 'body:foo' DESC
LIMIT 10;
  • SELECT フィールド
  • ORDER BY ... DESC 並べ替え
  • LIMIT
テキストの完全一致
SELECT id, body
FROM elasticsearch_table
WHERE body = 'foo'
LIMIT 10;
  • SELECT フィールド
  • WHERE フィルタ
  • LIMIT
単一フィールド式
SELECT id, body
FROM elasticsearch_table
WHERE id > 10
ORDER BY metadata <@> 'body:foo'
LIMIT 10;
  • SELECT フィールド
  • WHERE フィルタ
定数式
SELECT id, body
FROM elasticsearch_table
WHERE id > (1+1)
LIMIT 10;
  • SELECT フィールド
  • WHERE フィルタ
  • LIMIT
関数を含む式
SELECT id, body
FROM elasticsearch_table
WHERE id > CEIL(3.14)
LIMIT 10;
  • SELECT フィールド
複数フィールド式
SELECT id, body
FROM elasticsearch_table
WHERE dbl_field < flt_field
LIMIT 10;
  • SELECT フィールド
スコア フィルタリング
SELECT id, body, (metadata <@> 'body:bar') AS score
FROM elasticsearch_table
WHERE score > 0.5
ORDER by score desc
LIMIT 10;
  • SELECT フィールド
  • ORDER BY ... DESC 並べ替え
LIKE などの演算子
SELECT id, body
FROM elasticsearch_table
WHERE id > 10 AND body LIKE '%foo%'
LIMIT 10;
  • SELECT フィールド
  • WHERE id > 10 フィルタ
未加工のクエリ
SELECT id, body
FROM elasticsearch_table
WHERE id < 10
ORDER BY metadata <@> $${"query": { "match_all": {}}}$$ DESC
LIMIT 10;
  • SELECT フィールド
  • ORDER BY ... DESC 並べ替え