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

Lindorm:基本機能

最終更新日:Mar 07, 2025

Java Low Level REST Client は、Elasticsearch が提供する基本的な REST クライアントです。クライアントの API 操作は、データのエンコードやデコードを行いません。Lindorm ベクトルエンジンは Elasticsearch プロトコルと互換性があり、スカラー検索、ベクトル検索、全文検索機能の組み合わせをサポートしています。リクエストとレスポンスの処理方法をカスタマイズする場合、Java Low Level REST Client を使用してベクトルエンジンにアクセスできます。

前提条件

  • Java 開発キット(JDK) 1.8 以降がインストールされている。

  • ベクトルエンジンが有効化されている。ベクトルエンジンの有効化方法の詳細については、「ベクトルエンジンを有効化する」をご参照ください。

  • LindormSearch が有効化されている。詳細については、「LindormSearch を有効化する」をご参照ください。

  • クライアントの IP アドレスが Lindorm インスタンスのホワイトリストに追加されている。詳細については、「ホワイトリストを設定する」をご参照ください。

準備

Java Low Level REST Client をインストールする

たとえば、Maven プロジェクトの pom.xml ファイルに次の依存関係を追加できます。サンプルコード:

<dependency>
  <groupId>org.elasticsearch.client</groupId>
  <artifactId>elasticsearch-rest-client</artifactId>
  <version>7.10.0</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-core</artifactId>
  <version>2.8.2</version>
</dependency>
<dependency>
  <groupId>org.apache.logging.log4j</groupId>
  <artifactId>log4j-api</artifactId>
  <version>2.7</version>
</dependency>

LindormSearch に接続する

// Elasticsearch 用の LindormSearch エンドポイントを指定します。
String search_url = "ld-t4n5668xk31ui****-proxy-search-public.lindorm.rds.aliyuncs.com";
int search_port = 30070;

// ユーザー名とパスワードを指定します。
String username = "user";
String password = "test";
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(search_url, search_port));
restClientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
  @Override
  public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
    return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
  }
});

パラメーター

パラメーター

説明

search_url

[elasticsearch 用 Lindormsearch エンドポイント]。エンドポイントの取得方法の詳細については、「エンドポイントを表示する」をご参照ください。

重要
  • アプリケーションが ECS インスタンスにデプロイされている場合は、セキュリティを強化し、ネットワークレイテンシを低減するために、VPC を使用して Lindorm インスタンスに接続することをお勧めします。

  • アプリケーションがローカルサーバーにデプロイされており、インターネット経由で Lindorm インスタンスに接続する必要がある場合は、Lindorm コンソールでインスタンスのパブリックエンドポイントを有効にするために、次の手順を実行できます。左側のナビゲーションウィンドウで、[データベース接続] をクリックします。表示されるページで、[検索エンジン] タブをクリックします。次に、右上隅にある [パブリックエンドポイントを有効にする] をクリックします。

  • VPC を使用して Lindorm インスタンスにアクセスする場合は、search_url の値に [elasticsearch 用 Lindormsearch VPC エンドポイント] を指定します。インターネットを使用して Lindorm インスタンスにアクセスする場合は、search_url の値に [elasticsearch 用 Lindormsearch インターネットエンドポイント] を指定します。

search_port

[elasticsearch 用 Lindormsearch エンドポイント]へのアクセスに使用するポート。このパラメーターの値は 30070 に固定されています。

username

LindormSearch へのアクセスに使用するユーザー名とパスワード。

デフォルトのユーザー名とパスワードを取得するには、次の手順を実行できます。左側のナビゲーションウィンドウで、[データベース接続] をクリックします。表示されるページで、[検索エンジン] タブをクリックします。次に、このタブに表示されているユーザー名とパスワードを確認します。

password

ベクトルインデックスを作成する

HNSW インデックス

次のサンプルコードは、vector_test インデックスを作成する方法の例を示しています。

String indexName = "vector_test";

// インデックスを作成します。
Request indexRequest = new Request("PUT", "/" + indexName);
indexRequest.setJsonEntity("{\n" +
  " \"settings\" : {\n" +
  "    \"index\": {\n" +
  "      \"number_of_shards\": 2,\n" +
  "      \"knn\": true\n" +
  "    }\n" +
  "  },\n" +
  "  \"mappings\": {\n" +
  "    \"_source\": {\n" +
  "      \"excludes\": [\"vector1\"]\n" +
  "    },\n" +
  "    \"properties\": {\n" +
  "      \"vector1\": {\n" +
  "        \"type\": \"knn_vector\",\n" +
  "        \"dimension\": 3,\n" +
  "        \"data_type\": \"float\",\n" +
  "        \"method\": {\n" +
  "          \"engine\": \"lvector\",\n" +
  "          \"name\": \"hnsw\", \n" +
  "          \"space_type\": \"l2\",\n" +
  "          \"parameters\": {\n" +
  "            \"m\": 24,\n" +
  "            \"ef_construction\": 500\n" +
  "         }\n" +
  "       }\n" +
  "      },\n" +
  "      \"field1\": {\n" +
  "        \"type\": \"long\"\n" +
  "      }\n" +
  "    }\n" +
  "  }\n" +
  "}");
Response response = restClient.performRequest(indexRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("responseBody = " + responseBody);

IVFPQ インデックス

次のサンプルコードは、vector_ivfpq_test インデックスを作成する方法の例を示しています。

String indexName = "vector_ivfpq_test";
Request indexRequest = new Request("PUT", "/" + indexName);
int dim = 3;
String createIndexJson = "{\n" +
  "  \"settings\": {\n" +
  "    \"index\": {\n" +
  "      \"number_of_shards\": 4,\n" +
  "      \"knn\": true,\n" +
  "      \"knn.offline.construction\": true\n" +
  "    }\n" +
  "  },\n" +
  "  \"mappings\": {\n" +
  "    \"_source\": {\n" +
  "      \"excludes\": [\"vector1\"]\n" +
  "    },\n" +
  "    \"properties\": {\n" +
  "      \"vector1\": {\n" +
  "        \"type\": \"knn_vector\",\n" +
  "        \"dimension\": %d,\n" +
  "        \"data_type\": \"float\",\n" +
  "        \"method\": {\n" +
  "          \"engine\": \"lvector\",\n" +
  "          \"name\": \"ivfpq\",\n" +
  "          \"space_type\": \"cosinesimil\",\n" +
  "          \"parameters\": {\n" +
  "            \"m\": %d,\n" +
  "            \"nlist\": 10000,\n" +
  "            \"centroids_use_hnsw\": true,\n" +
  "            \"centroids_hnsw_m\": 48,\n" +
  "            \"centroids_hnsw_ef_construct\": 500,\n" +
  "            \"centroids_hnsw_ef_search\": 200\n" +
  "          }\n" +
  "        }\n" +
  "      },\n" +
  "      \"field1\": {\n" +
  "        \"type\": \"long\"\n" +
  "      }\n" +
  "    }\n" +
  "  }\n" +
  "}"

createIndexJson = String.format(createIndexJson, dim, dim);
indexRequest.setJsonEntity(createIndexJson);
Response response = restClient.performRequest(indexRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("responseBody = " + responseBody);

スパースベクトルインデックス

次のサンプルコードは、vector_sparse_test インデックスを作成する方法の例を示しています。

String indexName = "vector_sparse_test";

// インデックスを作成します。
Request indexRequest = new Request("PUT", "/" + indexName);
indexRequest.setJsonEntity("{\n" +
  " \"settings\" : {\n" +
  "    \"index\": {\n" +
  "      \"number_of_shards\": 2,\n" +
  "      \"knn\": true\n" +
  "    }\n" +
  "  },\n" +
  "  \"mappings\": {\n" +
  "    \"_source\": {\n" +
  "      \"excludes\": [\"vector1\"]\n" +
  "    },\n" +
  "    \"properties\": {\n" +
  "      \"vector1\": {\n" +
  "        \"type\": \"knn_vector\",\n" +
  "        \"data_type\": \"sparse_vector\",\n" +
  "        \"method\": {\n" +
  "          \"engine\": \"lvector\",\n" +
  "          \"name\": \"sparse_hnsw\",\n" +
  "          \"space_type\": \"innerproduct\",\n" +
  "          \"parameters\": {\n" +
  "            \"m\": 24,\n" +
  "            \"ef_construction\": 200\n" +
  "         }\n" +
  "       }\n" +
  "      },\n" +
  "      \"field1\": {\n" +
  "        \"type\": \"long\"\n" +
  "      }\n" +
  "    }\n" +
  "  }\n" +
  "}");
Response response = restClient.performRequest(indexRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("responseBody = " + responseBody);

データを書き込む

ベクトル列を含むインデックスにデータを書き込む方法は、一般的なインデックスにデータを書き込む方法と同じです。

1 行のデータを書き込む

次のサンプルコードは、vector_test インデックスにデータを書き込む方法の例を示しています。

String indexName = "vector_test";
String documentId = "1";
String jsonString = "{ \"field1\": 1, \"vector1\": [1.2, 1.3, 1.4] }";
Request request = new Request(
  "PUT", // ドキュメント ID が指定されている場合は、PUT メソッドを使用します。
  "/" + indexName + "/_doc/" + documentId);
request.setJsonEntity(jsonString);
response = restClient.performRequest(request);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("writeDoc responseBody = " + responseBody);

複数の行のデータを同時に書き込む

// 複数の行のデータを同時に書き込みます。
Random random = new Random();
Request bulkRequest = new Request("POST", "/_bulk");
StringBuilder bulkJsonBuilder = new StringBuilder();
for (int i = 2; i < 10; i++) {
  // サンプルコードのフィールドと値をビジネスの実際のフィールドと値に置き換えます。
  bulkJsonBuilder.append("{\"index\":{\"_index\":\"").append(indexName).append("\",\"_id\":\"").append(i).append("\"}}").append("\n");
  String value = String.valueOf(random.nextInt());
  float[] floatArray = {random.nextFloat(), random.nextFloat(), random.nextFloat()};
  String floatArrayString = Arrays.toString(floatArray);
  System.out.println(i + " " + value + " " + floatArrayString);
  bulkJsonBuilder.append("{\"field1\":\"").append(value).append("\",\"vector1\":\"").append(floatArrayString).append("\"}").append("\n");
}
bulkRequest.setJsonEntity(bulkJsonBuilder.toString());
response = restClient.performRequest(bulkRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("bulkWriteDoc responseBody = " + responseBody);

// 書き込まれたデータを表示するために、更新リクエストを開始します。
response = restClient.performRequest(new Request("POST", "/" + indexName + "/_refresh"));
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("responseBody = " + responseBody);

スパースベクトルを書き込む

前述の方法を使用して、スパースベクトルを書き込むことができます。この場合、vector1 の形式を変更する必要があります。

// 1 つのデータエントリを書き込みます。
String documentId = "1";
String jsonString = "{ \"field1\": 1, \"vector1\": {\"indices\": [10, 12, 16], \"values\": [1.2, 1.3, 1.4]} }";
Request request = new Request(
  "PUT", // ドキュメント ID が指定されている場合は、PUT メソッドを使用します。
  "/" + indexName + "/_doc/" + documentId);
request.setJsonEntity(jsonString);
response = restClient.performRequest(request);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("writeDoc responseBody = " + responseBody);

インデックスを構築する

重要
  • デフォルトでは、index.knn.offline.construction パラメーターは、IVFPQ インデックス以外のすべてのインデックスタイプで false に設定されています。このように、オンラインインデックス作成は手動介入なしで実装されます。

  • IVFPQ インデックスを作成する場合は、index.knn.offline.construction パラメーターを明示的に true に設定する必要があります。インデックス構築をトリガーする場合は、十分な量のデータが書き込まれていることを確認してください。データ量は 256 レコードを超え、nlist パラメーターの値の 30 倍以上である必要があります。

  • インデックスを手動で構築した後、データの書き込みとクエリを実行できます。インデックスを再度構築する必要はありません

インデックス構築をトリガーする

次のサンプルコードは、vector_ivfpq_test インデックスを構築する方法の例を示しています。

// インデックスを構築します。
Request buildIndexRequest = new Request("POST", "/_plugins/_vector/index/build");
String jsonString = "{ \"indexName\": \"vector_ivfpq_test\", \"fieldName\": \"vector1\", \"removeOldIndex\": \"true\" }";
response = restClient.performRequest(buildIndexRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("buildIndex responseBody = " + responseBody);

パラメーター

パラメーター

必須

説明

indexName

はい

テーブル名。例:vector_ivfpq_test

fieldName

はい

インデックスを構築するフィールド。例:vector1

removeOldIndex

はい

インデックスを構築するときに既存のインデックスを削除するかどうかを指定します。有効な値:

  • true:インデックス構築がトリガーされると、既存のインデックスデータが削除されます。構築が完了した後でのみ kNN クエリを実行できます。

    重要

    実際のビジネスでは、値を true に設定することをお勧めします。

  • false(デフォルト値):既存のインデックスを保持します。これは検索パフォーマンスに影響を与える可能性があります。

出力例:

{
  "payload": ["default_vector_ivfpq_test_vector1"]
}

出力は、インデックスが構築されるときに生成される タスク ID です。

インデックスステータスを表示する

// インデックスステータスを表示します。
Request buildIndexRequest = new Request("GET", "/_plugins/_vector/index/tasks");
String jsonString = "{ \"indexName\": \"vector_ivfpq_test\", \"fieldName\": \"vector1\", \"taskIds\": \"[default_vector_ivfpq_test_vector1]\" }";
buildIndexRequest.setJsonEntity(jsonString);
Response response = restClient.performRequest(buildIndexRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("queryBuildIndex responseBody = " + responseBody);

taskIds は、インデックス構築プロセスがトリガーされるときに生成される タスク ID のリストを示します。\"taskIds\": \"[]\" のように、taskIds に空の配列を指定できます。これは、特定のタスク ID を指定するのと同じ効果があります。

出力例:

{
  "payload": ["task: default_vector_ivfpq_test_vector1, stage: FINISH, innerTasks: xxx, info: finish building"]
}

stage は、インデックス構築ステータスを示します。有効な値:START、TRAIN、BUILDING、ABORT、FINISH、および FAIL。

説明

ほとんどの場合、/index/abort 操作を呼び出してインデックスの構築を停止できます。

インデックス構築を停止する

インデックス構築プロセスを停止します。FINISH 状態のインデックスの構築を停止するために /index/abort 操作を呼び出すことはできません。

// インデックスの作成を停止します。
Request buildIndexRequest = new Request("POST", "/_plugins/_vector/index/tasks/abort");
String jsonString = "{ \"indexName\": \"vector_ivfpq_test\", \"fieldName\": \"vector1\", \"taskIds\": \"[\"default_vector_ivfpq_test_vector1\"]\" }";
buildIndexRequest.setJsonEntity(jsonString);
Response response = restClient.performRequest(buildIndexRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("abortBuildIndex responseBody = " + responseBody);

出力例:

{
  "payload":["Task: default_vector_ivfpq_test_vector1 remove success"]
}

データをクエリする

純粋なベクトルデータをクエリする

k 近傍法(kNN)構造を使用して、純粋なベクトルデータをクエリできます。

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
jsonString = "{"
  + "\"size\": 10,"
  + "\"query\": {"
  +     "\"knn\": {"
  +         "\"vector1\": {"
  +             "\"vector\": [2.2, 2.3, 2.4],"
  +             "\"k\": 10"
  +         "}"
  +     "}"
  + "},"
  + "\"ext\": {\"lvector\": {\"min_score\": \"0.1\"}}"
  + "}";
searchRequest.setJsonEntity(jsonString);
response = restClient.performRequest(searchRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

パラメーター

パラメーター構造

パラメーター

必須

説明

knn

vector

はい

クエリで使用されるベクトル。

k

はい

返される最も類似したデータレコードの数。

重要

純粋なベクトル検索シナリオでは、size パラメーターと k パラメーターを同じ値に設定することをお勧めします。

ext

lvector.min_score

いいえ

類似度のしきい値。返されるベクトルスコアはこの値より大きくなければなりません。返されるベクトルスコアの範囲は 0 から 1 です。

最小値:[0, +inf]。デフォルト値:0

lvector.filter_type

いいえ

統合クエリのモード。有効な値:

  • pre_filter:構造化データをフィルタリングしてから、ベクトルデータをクエリします。

  • post_filter:ベクトルデータをクエリしてから、構造化データをフィルタリングします。

  • efficient_filter:内部コストの見積もりに基づいて、pre_filter または post_filter を自動的に選択します。

    重要

    LindormSearch のバージョンは3.9.10 以降である必要があります。

このパラメーターはデフォルトでは空です。

lvector.ef_search

いいえ

インデックス構築中の動的リストの長さ。このパラメーターは HNSW アルゴリズムにのみ適用されます。

有効な値:1 から 1000。デフォルト値:100

lvector.nprobe

いいえ

クエリするクラスターユニットの数。目的の効果を達成するために、取得率の要件に基づいてこのパラメーターの値を調整します。値が大きいほど、取得率が高く、検索パフォーマンスが低くなります。

最小値:1。最大値:method.parameters.nlist パラメーターで指定された値。このパラメーターにはデフォルト値がありません。

重要

このパラメーターは IVFPQ アルゴリズムにのみ適用されます。

lvector.reorder_factor

いいえ

元のベクトルを使用して検索結果を並べ替えます。IVFPQ アルゴリズムによって計算された距離は量子化された距離であるため、精度がいくらか失われる可能性があります。したがって、元のベクトルを使用して並べ替える必要があります。並べ替えの割合は k * reorder_factor パラメーターで指定されます。並べ替えは取得精度を向上させるために使用されますが、パフォーマンスオーバーヘッドが増加する可能性があります。

有効な値:1 から 200。デフォルト値:10

重要
  • このパラメーターは IVFPQ アルゴリズムにのみ適用されます。

  • k パラメーターの値が小さい場合は、このパラメーターを 5 に設定します。k パラメーターの値が 100 より大きい場合は、このパラメーターを 1 に設定します。

lvector.client_refactor

いいえ

システムパフォーマンスを向上させるために、各シャード内ではなくシステムの上位層で並べ替えを実行するかどうかを指定します。有効な値:

  • true

  • false(デフォルト)

lvector.k_expand_scope

いいえ

近似クエリに efficient_filter モードを使用し、システムが post_filter モードを自動的に選択する場合、パフォーマンスを向上させるために、k パラメーターの代わりに k_expand_scope パラメーターを使用する必要があります。デフォルト値:1000

この例では、HNSW インデックス vector_test が使用されています。出力例:

出力を表示

{
    "took": 65,
    "timed_out": false,
    "terminated_early": false,
    "num_reduce_phases": 0,
    "_shards": {
        "total": 2,
        "successful": 2,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 10,
            "relation": "eq"
        },
        "max_score": 0.25,
        "hits": [
            {
                "_index": "vector_test",
                "_id": "1",
                "_score": 0.25
            },
            {
                "_index": "vector_test",
                "_id": "32",
                "_score": 0.14561969
            },
            {
                "_index": "vector_test",
                "_id": "122",
                "_score": 0.13761099
            },
            {
                "_index": "vector_test",
                "_id": "80",
                "_score": 0.13138853
            },
            {
                "_index": "vector_test",
                "_id": "12",
                "_score": 0.12602884
            },
            {
                "_index": "vector_test",
                "_id": "120",
                "_score": 0.123480916
            },
            {
                "_index": "vector_test",
                "_id": "39",
                "_score": 0.12126313
            },
            {
                "_index": "vector_test",
                "_id": "27",
                "_score": 0.117812514
            },
            {
                "_index": "vector_test",
                "_id": "29",
                "_score": 0.11756193
            },
            {
                "_index": "vector_test",
                "_id": "81",
                "_score": 0.11755075
            }
        ]
    }
}

指定したフィールドを返す

クエリで指定したフィールドを返すには、"_source": ["field1", "field2"] を指定します。すべての非ベクトルフィールドを返すには、"_source": true を指定します。次のサンプルコードは、vector_test インデックスをクエリする方法の例を示しています。

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
jsonString = "{"
  + "\"size\": 10,"
  + "\"_source\": [\"field1\"],"
  + "\"query\": {"
  +     "\"knn\": {"
  +         "\"vector1\": {"
  +             "\"vector\": [2.2, 2.3, 2.4],"
  +             "\"k\": 10"
  +         "}"
  +     "}"
  + "},"
  + "\"ext\": {\"lvector\": {\"min_score\": \"0.1\"}}"
  + "}";
searchRequest.setJsonEntity(jsonString);
response = restClient.performRequest(searchRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

出力例:

出力を表示

{
  "took": 31,
  "timed_out": false,
  "terminated_early": false,
  "num_reduce_phases": 0,
  "_shards": {
    "total": 2,
    "successful": 2,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 10,
      "relation": "eq"
    },
    "max_score": 0.25,
    "hits": [
      {
        "_index": "vector_test",
        "_id": "1",
        "_score": 0.25,
        "_source": {
          "field1": 1
        }
      },
      {
        "_index": "vector_test",
        "_id": "67",
        "_score": 0.15348388,
        "_source": {
          "field1": "-487556052"
        }
      },
      {
        "_index": "vector_test",
        "_id": "83",
        "_score": 0.1416535,
        "_source": {
          "field1": "1733994439"
        }
      },
      {
        "_index": "vector_test",
        "_id": "43",
        "_score": 0.13119161,
        "_source": {
          "field1": "-747555255"
        }
      },
      {
        "_index": "vector_test",
        "_id": "54",
        "_score": 0.1267109,
        "_source": {
          "field1": "-1544683361"
        }
      },
      {
        "_index": "vector_test",
        "_id": "110",
        "_score": 0.12533507,
        "_source": {
          "field1": "882740211"
        }
      },
      {
        "_index": "vector_test",
        "_id": "48",
        "_score": 0.124014825,
        "_source": {
          "field1": "-513152633"
        }
      },
      {
        "_index": "vector_test",
        "_id": "40",
        "_score": 0.12398689,
        "_source": {
          "field1": "1360426997"
        }
      },
      {
        "_index": "vector_test",
        "_id": "60",
        "_score": 0.12019993,
        "_source": {
          "field1": "10377260"
        }
      },
      {
        "_index": "vector_test",
        "_id": "61",
        "_score": 0.12009792,
        "_source": {
          "field1": "-2097991339"
        }
      }
    ]
  }
}

HSNW アルゴリズムを使用する

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
jsonString = "{"
  + "\"size\": 10,"
  + "\"query\": {"
  +     "\"knn\": {"
  +         "\"vector1\": {"
  +             "\"vector\": [2.2, 2.3, 2.4],"
  +             "\"k\": 10"
  +         "}"
  +     "}"
  + "},"
  + "\"ext\": {\"lvector\": {\"ef_search\": \"100\"}}"
  + "}";
searchRequest.setJsonEntity(jsonString);
response = restClient.performRequest(searchRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

IVFPQ アルゴリズムを使用する

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
jsonString = "{"
  + "\"size\": 10,"
  + "\"query\": {"
  +     "\"knn\": {"
  +         "\"vector1\": {"
  +             "\"vector\": [2.2, 2.3, 2.4],"
  +             "\"k\": 10"
  +         "}"
  +     "}"
  + "},"
  + "\"ext\": {\"lvector\": {\"nprobe\": \"60\", \"reorder_factor\": \"2\"}}"
  + "}";
searchRequest.setJsonEntity(jsonString);
response = restClient.performRequest(searchRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);
重要
  • k パラメーターの値が 100 より大きい場合は、reorder_factor パラメーターを 1 に設定します。

  • nlist パラメーターの値が 10000 の場合、最初に nprobe パラメーターを 60 に設定して検索効果を確認できます。取得率をさらに向上させたい場合は、nprobe パラメーターを 80、100、120、140、160 などの大きな値に設定できます。 nprobe パラメーターの値を大きくすることによって発生するパフォーマンスオーバーヘッドは、reorder_factor パラメーターの値を調整することによって発生するパフォーマンスオーバーヘッドよりもはるかに小さくなります。ただし、nprobe パラメーターを過度に大きな値に設定しないことをお勧めします。

スパースベクトルをクエリする

前述の方法を使用して、スパースベクトルをクエリできます。この場合、vector1 の形式を変更する必要があります。

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
jsonString = "{"
  + "\"size\": 10,"
  + "\"query\": {"
  +     "\"knn\": {"
  +         "\"vector1\": {"
  +             "\"vector\": {\"indices\": [10, 45, 16], \"values\": [0.5, 0.5, 0.2]},"
  +             "\"k\": 10"
  +         "}"
  +     "}"
  + "}"
  + "}";
searchRequest.setJsonEntity(jsonString);
response = restClient.performRequest(searchRequest);
responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

統合クエリ

ベクトル列と共通列のクエリ条件を統合して、包括的なクエリ結果を返すことができます。実際のビジネスシナリオでは、近似クエリに post_filter モードを使用すると、より類似した検索結果が得られます。

近似クエリに pre-filter を使用する

kNN クエリ構造に filter を追加し、filter_type パラメーターを pre_filter に設定して、ベクトルデータをクエリする前に構造化データをフィルタリングできます。

説明

構造化データをフィルタリングするための上限は 10,000 データレコードです。

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
String jsonString = jsonString = "{"
  + "\"size\": 10,"
  + "\"query\": {"
  + "  \"knn\": {"
  + "    \"vector1\": {"
  + "      \"vector\": [2.2, 2.3, 2.4],"
  + "      \"filter\": {"
  + "        \"range\": {"
  + "          \"field1\": {"
  + "            \"gte\": 0"
  + "          }"
  + "        }"
  + "      },"
  + "      \"k\": 10"
  + "    }"
  + "  }"
  + "},"
  + "\"ext\": {\"lvector\": {\"filter_type\": \"pre_filter\"}}"
  + "}";
searchRequest.setJsonEntity(jsonString);
Response response = restClient.performRequest(searchRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

近似クエリに post-filter を使用する

kNN クエリ構造に filter を追加し、filter_type パラメーターを post_filter に設定して、構造化データをフィルタリングする前にベクトルデータをクエリできます。

説明

近似クエリに post_filter モードを使用する場合は、k パラメーターを大きな値に設定して、構造化データをフィルタリングする前により多くのベクトルデータをクエリできます。

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
String jsonString = "{\n" +
  "  \"size\": 10,\n" +
  "  \"query\": {\n" +
  "    \"knn\": {\n" +
  "      \"vector1\": {\n" +
  "        \"vector\": [2.2, 2.3, 2.4],\n" +
  "        \"filter\": {\n" +
  "          \"range\": {\n" +
  "            \"field1\": {\n" +
  "              \"gte\": 0\n" +
  "            }\n" +
  "          }\n" +
  "        },\n" +
  "        \"k\": 1000\n" +
  "      }\n" +
  "    }\n" +
  "  },\n" +
  "  \"ext\": {\n" +
  "    \"lvector\": {\n" +
  "      \"filter_type\": \"post_filter\"\n" +
  "    }\n" +
  "  }\n" +
  "}";
searchRequest.setJsonEntity(jsonString);
Response response = restClient.performRequest(searchRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

近似クエリに post_filter モードを使用する場合は、k パラメーターの値を大きくする必要があります。IVFPQ アルゴリズムを使用する場合は、reorder_factor パラメーターの値を調整する必要があります。サンプルコード:

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
String jsonString = "{\n" +
  "  \"size\": 10,\n" +
  "  \"query\": {\n" +
  "    \"knn\": {\n" +
  "      \"vector1\": {\n" +
  "        \"vector\": [2.2, 2.3, 2.4],\n" +
  "        \"filter\": {\n" +
  "          \"range\": {\n" +
  "            \"field1\": {\n" +
  "              \"gte\": 0\n" +
  "            }\n" +
  "          }\n" +
  "        },\n" +
  "        \"k\": 1000\n" +
  "      }\n" +
  "    }\n" +
  "  },\n" +
  "  \"ext\": {\n" +
  "    \"lvector\": {\n" +
  "      \"filter_type\": \"post_filter\",\n" +
  "      \"nprobe\": \"60\",\n" +
  "      \"reorder_factor\": \"1\"\n" +
  "    }\n" +
  "  }\n" +
  "}";
searchRequest.setJsonEntity(jsonString);
Response response = restClient.performRequest(searchRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);
重要
  • 近似クエリに post_filter モードを使用する場合は、k パラメーターの値を 10,000 から 20,000 の範囲内に設定できます。このように、レイテンシを 100 ミリ秒未満に短縮できます。k パラメーターの値が大きい場合は、reorder_factor パラメーターを 1 に設定します。

  • nlist パラメーターの値が 10000 の場合、最初に nprobe パラメーターを 60 に設定して検索効果を確認できます。検索効果を向上させるには、nprobe パラメーターを 80、100、120、140、160 などの大きな値に設定できます。 nprobe パラメーターの値を大きくすることによって発生するパフォーマンスオーバーヘッドは、reorder_factor パラメーターの値を調整することによって発生するパフォーマンスオーバーヘッドよりもはるかに小さくなります。ただし、nprobe パラメーターを過度に大きな値に設定しないことをお勧めします。

post_filter モードを使用してフィルター条件を追加して、近似クエリを実装することもできます。

// kNN クエリを実行します。
Request searchRequest = new Request("GET", "/" + indexName + "/_search");
String jsonString ="{\n" +
  "  \"size\": 10,\n" +
  "  \"query\": {\n" +
  "    \"knn\": {\n" +
  "      \"vector1\": {\n" +
  "        \"vector\": [2.2, 2.3, 2.4],\n" +
  "        \"k\": 10\n" +
  "      }\n" +
  "    }\n" +
  "  },\n" +
  "  \"post_filter\": {\n" +
  "    \"range\": {\n" +
  "      \"field1\": {\n" +
  "        \"gte\": 0\n" +
  "      }\n" +
  "    }\n" +
  "  }\n" +
  "}";
searchRequest.setJsonEntity(jsonString);
Response response = restClient.performRequest(searchRequest);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.println("search responseBody = " + responseBody);

一般的な操作

  • すべてのインデックスとそのデータ量をクエリします。

    Request request = new Request("GET", "/_cat/indices?v");
    Response response = restClient.performRequest(request);
    String responseBody = EntityUtils.toString(response.getEntity());
    System.out.println(responseBody);

    出力例:

    health status index        uuid        pri rep docs.count docs.deleted store.size pri.store.size
    green  open   vector_test  vector_test 2   0          2            0      6.8kb          6.8kb
  • 特定のインデックスのデータ量をクエリします。

    Request request = new Request("GET", "/" + indexName + "/_count");
    Response response = restClient.performRequest(request);
    String responseBody = EntityUtils.toString(response.getEntity());
    System.out.println(responseBody);

    出力例:

    {
      "count" : 2,
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "skipped" : 0,
        "failed" : 0
      }
    }
  • インデックス作成情報を表示します。

    Request request = new Request("GET", "/" + indexName);
    Response response = restClient.performRequest(request);
    String responseBody = EntityUtils.toString(response.getEntity());
    System.out.println(responseBody);

    出力例:

    出力を表示

    {
      "vector_test" : {
        "aliases" : { },
        "mappings" : {
          "_source" : {
            "excludes" : [
              "vector1"
            ]
          },
          "properties" : {
            "field1" : {
              "type" : "long"
            },
            "vector1" : {
              "type" : "knn_vector",
              "dimension" : 3,
              "data_type" : "float",
              "method" : {
                "engine" : "lvector",
                "space_type" : "l2",
                "name" : "hnsw",
                "parameters" : {
                  "ef_construction" : 200,
                  "m" : 24
                }
              }
            }
          }
        },
        "settings" : {
          "index" : {
            "search" : {
              "slowlog" : {
                "level" : "DEBUG",
                "threshold" : {
                  "fetch" : {
                    "warn" : "1s",
                    "trace" : "200ms",
                    "debug" : "500ms",
                    "info" : "800ms"
                  },
                  "query" : {
                    "warn" : "10s",
                    "trace" : "500ms",
                    "debug" : "1s",
                    "info" : "5s"
                  }
                }
              }
            },
            "indexing" : {
              "slowlog" : {
                "level" : "DEBUG",
                "threshold" : {
                  "index" : {
                    "warn" : "10s",
                    "trace" : "500ms",
                    "debug" : "2s",
                    "info" : "5s"
                  }
                }
              }
            },
            "number_of_shards" : "2",
            "provided_name" : "vector_test",
            "knn" : "true",
            "creation_date" : "1727169417350",
            "number_of_replicas" : "0",
            "uuid" : "vector_test",
            "version" : {
              "created" : "136287927"
            }
          }
        }
      }
    }
  • インデックス全体を削除します。

    Request deleteIndexRequest = new Request("DELETE", "/" + indexName);
    Response response = restClient.performRequest(deleteIndexRequest);
    String responseBody = EntityUtils.toString(response.getEntity());
    System.out.println("delIndex responseBody = " + responseBody);
  • クエリによってインデックスを削除します。

    request = new Request("POST", "/" + indexName + "/_delete_by_query");
    jsonString = "{\n" +
      "    \"query\": {\n" +
      "      \"term\": {\n" +
      "        \"field1\": 1\n" +
      "      }\n" +
      "    }\n" +
      "}";
    request.setJsonEntity(jsonString);
    response = restClient.performRequest(searchRequest);
    responseBody = EntityUtils.toString(response.getEntity());
    System.out.println("deleteByQuery responseBody = " + responseBody);