すべてのプロダクト
Search
ドキュメントセンター

Elasticsearch:Elasticsearch の kNN 検索機能を使用する

最終更新日:Jan 11, 2025

Alibaba Cloud Elasticsearch V8.0 以降では、k 近傍 (kNN) 検索機能が提供されています。この機能を使用すると、画像検索、ビデオフィンガープリント、顔認識、音声認識、商品レコメンデーションなど、さまざまな検索シナリオでビジネス要件を満たすために、ベクトル空間を迅速に使用できます。このトピックでは、kNN 検索機能の使用方法について説明します。

背景情報

Elasticsearch の kNN 検索機能の詳細については、「k 近傍 (kNN) 検索」をご参照ください。

前提条件

  • Alibaba Cloud Elasticsearch V8.X クラスタが作成されていること。この例では、Alibaba Cloud Elasticsearch V8.5.1 クラスタが作成されています。詳細については、「Alibaba Cloud Elasticsearch クラスタを作成する」をご参照ください。
  • ビジネスデータがベクトルデータに変換され、ベクトルデータが dense_vector タイプのフィールドに格納されていること。類似性メトリックに基づいてベクトルを設計できます。ドキュメントのベクトルがクエリベクトルに近いほど、ベクトルの類似度は高くなります。

注意事項

  • ベクトルデータは、dense_vector タイプのフィールドに格納する必要があります。 dense_vector タイプのフィールドは、集計または並べ替え操作をサポートしていません。
  • ネストされたタイプのフィールドは、近似 kNN 検索をサポートしていません。
  • クロス クラスタ検索シナリオで kNN 検索機能を使用する場合、ccs_minimize_roundtrips パラメータはサポートされていません。
  • デフォルトでは、kNN 検索は dfs_query_then_fetch 検索タイプを使用します。 kNN 検索機能を使用して検索を実行する場合、search_type パラメータを明示的に構成することはできません。

kNN 検索でサポートされている検索方法

kNN 検索では、次の検索方法がサポートされています。近似 kNN 検索完全 kNN 検索。次の表に、2 つの方法の違いを示します。
検索方法クエリインターフェースメモリ内ストレージマッピング要件説明
近似 kNN 検索search API を使用して kNN パラメータ を構成します。はい近似 kNN 検索を有効にするには、dense_vector タイプのフィールドの index パラメータを true に設定する必要があります。
説明 近似 kNN 検索方法は、Elasticsearch V8.0 以降でサポートされています。以前のバージョンの Elasticsearch では、dense_vector タイプのフィールドのマッピングで index パラメータを true に設定することはできません。 Elasticsearch クラスタが V8.0 より前のバージョンから V8.5 にアップグレードされ、クラスタで kNN 検索を実行する場合、作成するインデックスに dense_vector タイプのフィールドが含まれていることを確認する必要があります。近似 kNN 検索を実行するには、インデックスを再作成し、インデックスのマッピングで index パラメータを true に設定する必要もあります。
近似 kNN 検索では、レイテンシを低くするために、インデックス作成速度と精度が多少犠牲になります。
完全 kNN 検索ベクトル関数を使用して script_score クエリを使用します。はい検索効率を向上させるために、dense_vector タイプのフィールドの index パラメータを false に設定するか、パラメータを空のままにすることができます。script_score クエリは、一致する各ドキュメントをスキャンしてベクトル関数を計算します。これにより、検索速度が低下します。検索効率を向上させるために、ベクトル関数に渡すことができるドキュメントの数を制限する クエリ 句を構成できます。

近似 kNN 検索

パフォーマンスの最適化

近似 kNN 検索方法を使用すると、クエリベクトルに最も近い k 個のベクトルをすばやく見つけることができます。この検索方法のロジックは、他の検索方法のロジックとは異なります。近似 kNN 検索方法では、Elasticsearch クラスタのパフォーマンスに特別な要件があります。次の手順に基づいて、Elasticsearch クラスタのパフォーマンスを最適化できます。
  • Elasticsearch は、各セグメントの高密度ベクトルを Hierarchical Navigable Small World (HNSW) グラフに格納します。 HNSW グラフの構築には、ベクトルデータのインデックス作成中に長い時間がかかります。クライアントのタイムアウト期間を延長し、バルク書き込みリクエストを使用してデータを書き込むことをお勧めします。
  • 検索効率を向上させるために、インデックスのセグメント数を減らすか、インデックスのすべてのセグメントを 1 つのセグメントにマージすることができます。
  • Elasticsearch クラスタ内のデータノードのメモリ空間が、すべてのベクトルデータとインデックス構造によって占有される合計空間よりも大きいことを確認する必要があります。
  • 近似 kNN 検索中に、大量のデータを Elasticsearch クラスタに書き込んだり、データを更新したりしないでください。

インデックスの作成

近似 kNN 検索を実行するインデックスを作成する場合は、index パラメータを true に設定し、インデックスのマッピングで similarity パラメータを構成します。次のコードは、構成例を示しています。
PUT image-index
{
  "mappings": {
    "properties": {
      "image-vector": {
        "type": "dense_vector",
        "dims": 3,
        "index": true,
        "similarity": "l2_norm" // 類似度計算アルゴリズムを指定します。
      },
      "title": {
        "type": "text"
      },
      "file-type": {
        "type": "keyword"
      }
    }
  }
}
次の表に、dense_vector タイプのフィールドに関連する設定を定義するために使用されるパラメータを示します。詳細については、「dense-vector」をご参照ください。
パラメータ説明
type浮動小数点数を格納するために使用されるフィールドのデータ型。このパラメータを dense_vector に設定します。
dims各ベクトルの次元数。index パラメータを true に設定する場合、dims パラメータの値は 1024 を超えることはできません。index パラメータを false に設定する場合、dims パラメータの値は 2048 を超えることはできません。
index近似 kNN 検索用に新しいインデックスを生成するかどうかを指定します。近似 kNN 検索を実行するには、index パラメータを true に設定します。デフォルト値:false。
similarityクエリベクトルとドキュメントベクトルの間の類似度を計算するために使用されるアルゴリズム。index パラメータを true に設定する場合は、このパラメータを構成する必要があります。有効な値:
  • l2_norm:ベクトル間のユークリッド距離を計算します。スコアを計算するために使用される式:1/(1 + l2_norm(query, vector)^2)
  • dot_product:2 つのベクトルの内積を計算します。スコアの計算は、element_type パラメータによって異なります。
    • element_type パラメータを float に設定する場合、両方のベクトルを単位長に正規化する必要があります。スコアを計算するために使用される式:(1 + dot_product(query, vector))/2
    • element_type パラメータを byte に設定する場合、両方のベクトルは同じ長さである必要があります。ベクトルの長さが異なる場合、類似度に関する結果が不正確になる可能性があります。スコアを計算するために使用される式:0.5 + (dot_product(query, vector)/(32768 × dims))
  • cosine:ベクトル間の余弦類似度を計算します。 cosine アルゴリズムを使用する最も効率的な方法は、両方のベクトルを単位長に正規化して dot_product アルゴリズムを置き換えることです。スコアを計算するために使用される式:(1 + cosine(query, vector))/2
    重要 cosine アルゴリズムは、値が 0 のベクトルデータをサポートしていません。

データの書き込み

POST image-index/_bulk?refresh=true
{ "index": { "_id": "1" } }
{ "image-vector": [1, 5, -20], "title": "moose family", "file-type": "jpg" } // ベクトルデータ、タイトル、ファイルタイプを書き込みます。
{ "index": { "_id": "2" } }
{ "image-vector": [42, 8, -15], "title": "alpine lake", "file-type": "png" } // ベクトルデータ、タイトル、ファイルタイプを書き込みます。
{ "index": { "_id": "3" } }
{ "image-vector": [15, 11, 23], "title": "full moon", "file-type": "jpg" } // ベクトルデータ、タイトル、ファイルタイプを書き込みます。

近似 kNN 検索の実行

近似 kNN 検索を実行するには、search API を使用して kNN パラメータを構成する必要があります。
説明 kNN search API は、V8.4 以降の Elasticsearch では非推奨となっています。近似 kNN 検索を実行するには、search API で kNN パラメータを構成できます。
POST image-index/_search
{
  "knn": {
    "field": "image-vector", // 検索対象のベクトルフィールド名を指定します。
    "query_vector": [-5, 9, -12], // クエリベクトルを指定します。
    "k": 10, // 返す最近傍の数を指定します。
    "num_candidates": 100 // シャードごとに検索する必要がある最近傍候補の数を指定します。
  },
  "fields": [ "title", "file-type" ] // 返すフィールドを指定します。
}
次の表に、kNN パラメータを示します。詳細については、「Search API」をご参照ください。
パラメータ必須説明
fieldはい検索するベクトルフィールドの名前。
query_vectorはいクエリベクトル。クエリベクトルは、field パラメータで指定されたベクトルフィールドと同じ次元数である必要があります。
kはい返す最近傍の数。k パラメータの値は、num_candidates パラメータの値よりも小さくなければなりません。
num_candidatesはいシャードごとに検索する必要がある最近傍候補の数。値は 10000 を超えることはできません。
説明 num_candidates パラメータの値が大きいほど、k パラメータの値の精度は高くなります。ただし、検索速度は低下します。
フィルターいいえドキュメントをフィルタリングするために使用されるドメイン固有言語 ( DSL ) ステートメント。近似 kNN 検索は、フィルター条件に一致する上位 k 件のドキュメントを返します。このパラメーターを構成しない場合は、すべてのドキュメントが一致とみなされます。

正確な kNN 検索

インデックスの作成

PUT zl-index
{
  "mappings": {
    "properties": {
      "product-vector": {
        "type": "dense_vector",
        "dims": 5,
        "index": false
      },
      "price": {
        "type": "long"
      }
    }
  }
}
次の表に、dense_vector 型のフィールドに関連する設定を定義するために使用されるパラメーターの一部を示します。詳細については、「dense-vector」をご参照ください。
パラメーター説明
type浮動小数点数を格納するために使用されるフィールドのデータ型。このパラメーターを dense_vector に設定します。
dim各ベクトルの次元数。
index正確な kNN 検索の新しいインデックスを生成するかどうかを指定します。デフォルト値:false。正確な kNN 検索の場合、index パラメーターはオプションです。正確な kNN 検索の効率を向上させるために、このパラメーターを空のままにするか、false に設定できます。

データの書き込み

POST zl-index/_bulk?refresh=true
{ "index": { "_id": "1" } }
{ "product-vector": [230.0, 300.33, -34.8988, 15.555, -200.0], "price": 1599 }
{ "index": { "_id": "2" } }
{ "product-vector": [-0.5, 100.0, -13.0, 14.8, -156.0], "price": 799 }
{ "index": { "_id": "3" } }
{ "product-vector": [0.5, 111.3, -13.0, 14.8, -156.0], "price": 1099 }

正確な kNN 検索の実行

次のコードは、cosineSimilarity ベクトル関数を script_score クエリで指定し、script_score.query パラメーターでフィルター条件を構成して、ベクトル関数に渡すことができるドキュメントの数を制限する方法を示しています。
POST zl-index/_search
{
  "query": {
    "script_score": {
      "query" : {
        "bool" : {
          "filter" : {
            "range" : {
              "price" : {
                "gte": 1000
              }
            }
          }
        }
      },
      "script": {
        "source": "cosineSimilarity(params.queryVector, 'product-vector') + 1.0",
        "params": {
          "queryVector": [-0.5, 90.0, -10, 14.8, -156.0]
        }
      }
    }
  }
}
次の表に、script_score クエリでサポートされているベクトル関数を示します。詳細については、オープンソース Elasticsearch のドキュメントの「ベクトルフィールドの関数」をご参照ください。
関数説明
cosineSimilarityクエリベクトルとドキュメントベクトルのコサイン類似度を計算します。
dotProductクエリベクトルとドキュメントベクトルの内積を計算します。
l1normクエリベクトルとドキュメントベクトルの L1 距離(マンハッタン距離)を計算します。
l2normクエリベクトルとドキュメントベクトルの L2 距離(ユークリッド距離)を計算します。