All Products
Search
Document Center

Lindorm:Basic features

Last Updated:Jul 18, 2025

The Lindorm vector engine supports a combination of scalar, vector, and full-text search capabilities. The Java High Level REST Client provides easier-to-use APIs. For complex queries and analysis, you can use the Java Low Level REST Client to connect to the vector engine.

Prerequisites

  • Java Development Kit (JDK) 1.8 or later is installed.

  • The vector engine is activated. For more information about how to activate the vector engine, see Activate the vector engine.

  • LindormSearch is activated. For more information, see Activate LindormSearch.

  • The IP address of your client is added to the whitelist of the Lindorm instance. For more information, see Configure whitelists.

Preparations

Install the Java High Level REST Client

For example, you can add the following dependencies to the pom.xml file in your Maven project. Sample code:

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.10.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.20.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.20.0</version>
</dependency>

Connecting a search engine

// Specify the LindormSearch endpoint for Elasticsearch.
String search_url = "ld-t4n5668xk31ui****-proxy-search-public.lindorm.rds.aliyuncs.com";
int search_port = 30070;

String username = "user";
String password = "test";
final CredentialsProvider credentials_provider = new BasicCredentialsProvider();
credentials_provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));


RestHighLevelClient highClient = new RestHighLevelClient(
  RestClient.builder(new HttpHost( search_url, search_port, "http")).setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
      return httpClientBuilder.setDefaultCredentialsProvider(credentials_provider);
    }
  })
);

Parameter

Description

search_url

The LindormSearch endpoint for Elasticsearch. For more information about how to obtain the endpoint, see LindormSearch endpoint for Elasticsearch.

Important
  • If your application is deployed on an ECS instance, we recommend that you use a VPC to connect to the Lindorm instance to ensure higher security and lower network latency.

  • If your application is deployed on a local server and needs to connect to the Lindorm instance over the Internet, you can perform the following steps to enable the public endpoint of the instance in the Lindorm console: In the left-side navigation pane, click Database Connections. On the page that appears, click the Search Engine tab. Then, click Enable Public Endpoint in the upper-right corner.

  • If you use a VPC to access the Lindorm instance, specify the LindormSearch VPC endpoint for Elasticsearch in the value of search_url. If you use the Internet to access the Lindorm instance, specify the LindormSearch Internet endpoint for Elasticsearch in the value of search_url.

search_port

The port used to access the LindormSearch endpoint for Elasticsearch. The value of this parameter is fixed to 30070.

username

The username and password used to connect to LindormSearch.

You can perform the following steps to obtain the default username and password: In the left-side navigation pane, click Database Connections. On the page that appears, click the Search Engine tab. Then, view the username and password displayed on this tab.

password

Create a vector index

Note

In this example, the Map.of syntax is supported only by JDK 9 or later. If your JDK is earlier than this version, you can modify the syntax based on your actual JDK version.

HNSW index

String indexName = "vector_hnsw_test";

CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
{
  // Create settings
  Map<String, Object> indexMap = new HashMap<>();
  indexMap.put("number_of_shards", 2);
  indexMap.put("knn", true);
  Map<String, Object> settings = new HashMap<>();
  settings.put("index", indexMap);
  createIndexRequest.settings(settings);
}

{
  // Create mappings
  Map<String, Object> source = new HashMap<>();
  source.put("excludes", new String[] { "vector1" });

  // Create a map for "method.parameters"
  Map<String, Object> parameters = new HashMap<>();
  parameters.put("m", 24);
  parameters.put("ef_construction", 500);

  // Create a map for "method"
  Map<String, Object> method = new HashMap<>();
  method.put("engine", "lvector");
  method.put("name", "hnsw");
  method.put("space_type", "l2");
  method.put("parameters", parameters);

  // Create a map for "vector1"
  Map<String, Object> vector1 = new HashMap<>();
  vector1.put("type", "knn_vector");
  vector1.put("dimension", 3);
  vector1.put("method", method);

  // Create a map for the properties
  Map<String, Object> properties = new HashMap<>();
  properties.put("vector1", vector1);
  properties.put("field1", Map.of("type", "long"));

  // Create the mappings map
  Map<String, Object> mappings = new HashMap<>();
  mappings.put("_source", source);
  mappings.put("properties", properties);
  createIndexRequest.mapping(mappings);
}

CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println("createIndexResponse: " + createIndexResponse);

IVFPQ index

String indexName = "vector_ivfpq_test";

CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
{
  // Create settings
  Map<String, Object> indexMap = new HashMap<>();
  indexMap.put("number_of_shards", 2);
  indexMap.put("knn", true);
  indexMap.put("knn.offline.construction", true);
  Map<String, Object> settings = new HashMap<>();
  settings.put("index", indexMap);
  createIndexRequest.settings(settings);
}

{
  // Create mappings
  Map<String, Object> source = new HashMap<>();
  Map<String, Object> source = new HashMap<>();
  source.put("excludes", new String[] { "vector1" });
  mappings.put("_source", source);

  Map<String, Object> properties = new HashMap<>();
  int dim = 3;
  
  // Vector1 property
  Map<String, Object> vector1 = new HashMap<>();
  vector1.put("type", "knn_vector");
  vector1.put("dimension", dim);
  vector1.put("data_type", "float");

  Map<String, Object> method = new HashMap<>();
  method.put("engine", "lvector");
  method.put("name", "ivfpq");
  method.put("space_type", "cosinesimil");

  Map<String, Object> parameters = new HashMap<>();
  parameters.put("m", dim);
  parameters.put("nlist", 10000);
  parameters.put("centroids_use_hnsw", true);
  parameters.put("centroids_hnsw_m", 48);
  parameters.put("centroids_hnsw_ef_construct", 500);
  parameters.put("centroids_hnsw_ef_search", 200);
  method.put("parameters", parameters);

  vector1.put("method", method);
  properties.put("vector1", vector1);

  // Field1 property
  Map<String, Object> field1 = new HashMap<>();
  field1.put("type", "long");
  properties.put("field1", field1);

  mappings.put("properties", properties);
  createIndexRequest.mapping(mappings);
}

CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println("createIndexResponse: " + createIndexResponse);

Sparse vector index

String indexName = "vector_sparse_test";

CreateIndexRequest createIndexRequest = new CreateIndexRequest(indexName);
{
  // Create settings
  Map<String, Object> indexMap = new HashMap<>();
  indexMap.put("number_of_shards", 2);
  indexMap.put("knn", true);
  Map<String, Object> settings = new HashMap<>();
  settings.put("index", indexMap);
  createIndexRequest.settings(settings);
}

{
  // Create mappings
  Map<String, Object> source = new HashMap<>();
  Map<String, Object> source = new HashMap<>();
  source.put("excludes", new String[]{"vector1"});
  mappings.put("_source", source);

  Map<String, Object> properties = new HashMap<>();

  Map<String, Object> vector1 = new HashMap<>();
  vector1.put("type", "knn_vector");
  vector1.put("data_type", "sparse_vector");

  Map<String, Object> method = new HashMap<>();
  method.put("engine", "lvector");
  method.put("name", "sparse_hnsw");
  method.put("space_type", "innerproduct");

  Map<String, Object> parameters = new HashMap<>();
  parameters.put("m", 24);
  parameters.put("ef_construction", 200);
  method.put("parameters", parameters);

  vector1.put("method", method);

  properties.put("vector1", vector1);

  Map<String, Object> field1 = new HashMap<>();
  field1.put("type", "long");
  properties.put("field1", field1);

  mappings.put("properties", properties);
  createIndexRequest.mapping(mappings);
}

CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println("createIndexResponse: " + createIndexResponse);

Write data

You can write data to indexes that contain vector columns in the same manner as you write data to common indexes.

Write a single row of data

The following sample code provides an example on how to write data to the vector_test index:

Map<String, Object> fieldMap = new HashMap<>();
fieldMap.put("field1", 1);
fieldMap.put("vector1", new float[]{1.2f,1.3f,1.4f});
IndexRequest indexRequest = new IndexRequest("vector_test");
indexRequest.id("1");
indexRequest.source(fieldMap);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);

Write multiple rows of data at the same time

BulkRequest bulkRequest = new BulkRequest();
{
  Map<String, Object> fieldMap = new HashMap<>();
  fieldMap.put("field1", 1);
  fieldMap.put("vector1", new float[]{2.2f,2.3f,2.4f});
  IndexRequest indexRequest = new IndexRequest("vector_test");
  indexRequest.id("1");
  indexRequest.source(fieldMap);
  bulkRequest.add(indexRequest);
}
{
  Map<String, Object> fieldMap = new HashMap<>();
  fieldMap.put("field1", 1);
  fieldMap.put("vector1", new float[]{2.2f,2.3f,2.4f});
  IndexRequest indexRequest = new IndexRequest("vector_test");
  indexRequest.id("2");
  indexRequest.source(fieldMap);
  bulkRequest.add(indexRequest);
}
{
  Map<String, Object> fieldMap = new HashMap<>();
  fieldMap.put("field1", 2);
  fieldMap.put("vector1", new float[]{1.2f,1.3f,4.4f});
  IndexRequest indexRequest = new IndexRequest("vector_test");
  indexRequest.id("3");
  indexRequest.source(fieldMap);
  bulkRequest.add(indexRequest);
}
{
  DeleteRequest deleteRequest = new DeleteRequest("vector_test", "2");
  bulkRequest.add(deleteRequest);
}
{
  Map<String, Object> fieldMap = new HashMap<>();
  fieldMap.put("field1", 3);
  fieldMap.put("vector1", new float[]{2.2f,3.3f,4.4f});
  UpdateRequest updateRequest = new UpdateRequest();
  updateRequest.index("vector_test");
  updateRequest.id("1");
  updateRequest.doc(fieldMap);
  bulkRequest.add(updateRequest);
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);

Write a sparse vector

You can use the preceding method to write a sparse vector. In this case, you must modify the format of vector1.

Map<String, Object> vectorMap = new HashMap<>();
vectorMap.put("indices", Lists.of(10, 12, 16));
vectorMap.put("values", Lists.of(1.2, 1.3, 1.4));

Map<String, Object> fieldMap = new HashMap<>();
fieldMap.put("field1", 1);
fieldMap.put("vector1", vectorMap);

IndexRequest indexRequest = new IndexRequest("vector_test");
indexRequest.id("1");
indexRequest.source(fieldMap);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);

Build an index

The Java High Level REST Client does not support all custom plug-in APIs. You can use the Low Level REST Client to call _plugins APIs. For more information, see Build an index.

Query data

Define a separate class LVectorExtBuilder for use in pure vector data queries and integrated queries.

package com.aliyun.lindorm;

import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.search.SearchExtBuilder;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;

public class LVectorExtBuilder extends SearchExtBuilder {

  final Map<String, String> searchParams;
  protected final String name;

  public LVectorExtBuilder(String name, Map<String, String> searchParams) {
    this.name = name;
    this.searchParams = searchParams;
  }

  @Override
  public void writeTo(StreamOutput out) throws IOException {
    out.writeMap(searchParams, StreamOutput::writeString, StreamOutput::writeString);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    LVectorExtBuilder that = (LVectorExtBuilder) o;
    return Objects.equals(searchParams, that.searchParams) && Objects.equals(name, that.name);
  }

  @Override
  public int hashCode() {
    return Objects.hash(searchParams, name);
  }

  @Override
  public String getWriteableName() {
    return name;
  }

  @Override
  public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
    builder.startObject(name);
    for (Map.Entry<String, String> searchParam : searchParams.entrySet()) {
      builder.field(searchParam.getKey(), searchParam.getValue());
    }
    builder.endObject();
    return builder;
  }
}

Query pure vector data

float[] vectors = new float[]{2.2f,3.3f,4.4f};
SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
Map<String, Object> queryBody = new HashMap<>();
{
  Map<String, Object> vectorMap = new HashMap<>();
  vectorMap.put("vector", vectors);
  vectorMap.put("k", topK);
  queryBody.put("knn", Map.of(vectorColumn, vectorMap));
}
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("min_score", "0.8");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
searchRequest.source(searchSourceBuilder);
searchRequest.indices(index);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

Parameter description

Parameter structure

Parameter

Required

Description

knn

vector

Yes

The vector used in the query.

k

Yes

The number of the most similar data records returned.

ext

lvector.min_score

No

The similarity threshold. The returned vector score must be greater than this value. The returned vector score range is 0 to 1.

Minimum value: [0, +inf]. Default value: 0.

lvector.filter_type

No

The mode of the integrated query. Valid values:

  • pre_filter: filters structured data and then queries vector data.

  • post_filter: queries vector data and then filters structured data.

This parameter is empty by default.

lvector.ef_search

No

The length of the dynamic list during index query. This parameter is applicable only to the HNSW algorithm.

Valid values: 1 to 1000. Default value: 100.

lvector.nprobe

No

The number of cluster units that you want to query. Adjust the value of this parameter based on your recall rate requirements to achieve the desired effect. A larger value indicates a higher recall rate and lower search performance.

Minimum value: 1. Maximum value: the value specified by the method.parameters.nlist parameter. No default value.

Important

This parameter is applicable only to the IVFPQ algorithm.

lvector.reorder_factor

No

Creates a reordering of search results using original vectors. The distance calculated by the IVFPQ algorithm is a quantized distance, which may result in some precision loss. Therefore, reordering using original vectors is required. The reorder proportion is specified by the k * reorder_factor parameter. Reordering is used to improve the recall precision but may increase the performance overhead.

Valid values: 1 to 200. Default value: 10.

Important
  • This parameter is applicable only to the IVFPQ algorithm.

  • When the value of the k parameter is small, set this parameter to 5. When the value of the k parameter is greater than 100, set this parameter to 1.

Return a specified field

To return a specified field in a query, you can specify "_source": ["field1", "field2"] . To return all non-vector fields, you can specify "_source": true.

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
Map<String, Object> queryBody = new HashMap<>();
{
  Map<String, Object> vectorMap = new HashMap<>();
  vectorMap.put("vector", vectors);
  vectorMap.put("k", topK);
  queryBody.put("knn", Map.of(vectorColumn, vectorMap));
}
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("min_score", "0.8");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
// You can specify _source to contain attributes in the return values.
searchSourceBuilder.fetchSource(new FetchSourceContext(true, new String[]{"field1", "field2"}, null));
searchRequest.source(searchSourceBuilder);
searchRequest.indices(index);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

Use the HNSW algorithm for queries

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
Map<String, Object> queryBody = new HashMap<>();
{
  Map<String, Object> vectorMap = new HashMap<>();
  vectorMap.put("vector", vectors);
  vectorMap.put("k", topK);
  queryBody.put("knn", Map.of(vectorColumn, vectorMap));
}
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("ef_search", "100");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
// You can specify _source to contain attributes in the return values.
searchSourceBuilder.fetchSource(new FetchSourceContext(true, new String[]{"field1", "field2"}, null));
searchRequest.source(searchSourceBuilder);
searchRequest.indices(index);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

Use the IVFPQ algorithm for queries

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
Map<String, Object> queryBody = new HashMap<>();
{
  Map<String, Object> vectorMap = new HashMap<>();
  vectorMap.put("vector", vectors);
  vectorMap.put("k", topK);
  queryBody.put("knn", Map.of(vectorColumn, vectorMap));
}
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("nprobe", "60", "reorder_factor", "5");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
// You can specify _source to contain attributes in the return values.
searchSourceBuilder.fetchSource(new FetchSourceContext(true, new String[]{"field1", "field2"}, null));
searchRequest.source(searchSourceBuilder);
searchRequest.indices(index);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);
Important
  • If the value of the k parameter is greater than 100, set the reorder_factor parameter to 1.

  • When the value of the nlist parameter is 10000, you can set the nprobe parameter to 60 first to view the search effect. If you want to further increase the recall rate, you can set the nprobe parameter to a larger value, such as 80, 100, 120, 140, or 160. The performance overhead incurred by increasing the value of the nprobe parameter is much less than that of adjusting the value of the reorder_factor parameter. However, we recommend that you do not set nprobe parameter to an excessively large value.

Query a sparse vector

You can use the preceding method to query a sparse vector. In this case, you must modify the format of vector1.

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
Map<String, Object> queryBody = new HashMap<>();
{
  Map<String, Object> knn = new HashMap<>();
  Map<String, Object> vector1 = new HashMap<>();
  vector1.put("vector", new HashMap<String, Object>() {{
    put("indices", Arrays.asList(10, 45, 16));
    put("values", Arrays.asList(0.5, 0.5, 0.2));
  }});
  vector1.put("k", 10);
  knn.put("vector1", vector1);
  queryBody.put("knn", knn);
}
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
searchRequest.source(searchSourceBuilder);
searchRequest.indices(index);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

Integrated query

You can integrate query conditions of vector columns and common columns to return comprehensive query results. In actual business scenarios, using the post_filter mode for approximate queries provides more similar search results.

Use a pre-filter for approximate queries

You can add a filter to the kNN query structure and set the filter_type parameter to pre_filter to filter structured data before querying vector data.

Note

The upper limit to filter structured data is 10,000 data records.

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

// vectorColumn is the name of the vector column.
// field1 is the name of the attribute column.
Map<String, Object> queryBody = Map.of("knn", Map.of(vectorColumn, Map.of(
  "vector", vectors,
  "k", topK,
  "filter", Map.of("range", Map.of("filed1", Map.of("gte", 0))))));
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("filter_type", "pre_filter");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
searchRequest.source(searchSourceBuilder);
searchRequest.indices("vector_test");
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

Use a post-filter for approximate queries

You can add a filter to the kNN query structure and set the filter_type parameter to post_filter to query vector data before filtering structured data.

Note

When you use the post_filter mode for approximate queries, you can set the k parameter to a larger value to query more vector data before filtering structured data.

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

// vectorColumn is the name of the vector column.
// field1 is the name of the attribute column.
Map<String, Object> queryBody = Map.of("knn", Map.of(vectorColumn, Map.of(
  "vector", vectors,
  "k", topK,
  "filter", Map.of("range", Map.of("filed1", Map.of("gte", 0))))));
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("filter_type", "post_filter");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
searchRequest.source(searchSourceBuilder);
searchRequest.indices("vector_test");
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

If you use the post_filter mode for approximate queries, you must increase the value of the k parameter. If you use the IVFPQ algorithm, you must adjust the value of the reorder_factor parameter. Sample code:

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

// vectorColumn is the name of the vector column.
// field1 is the name of the attribute column.
Map<String, Object> queryBody = Map.of("knn", Map.of(vectorColumn, Map.of(
  "vector", vectors,
  "k", topK,
  "filter", Map.of("range", Map.of("filed1", Map.of("gte", 0))))));
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));
Map<String, String> ext = Map.of("filter_type", "post_filter", "nprobe", "60", "reorder_factor", "1");
searchSourceBuilder.ext(Collections.singletonList(new LVectorExtBuilder("lvector", ext)));
searchRequest.source(searchSourceBuilder);
searchRequest.indices("vector_test");
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);
Important
  • If you use the post_filter mode for approximate queries, you can set the value of the k parameter within the range of 10,000 to 20,000. This way, the latency can be shortened to below 100 milliseconds. If the value of the k parameter is large, set the reorder_factor parameter to 1.

  • When the value of the nlist parameter is 10000, you can set the nprobe parameter to 60 first to view the search effect. To improve the search effect, you can set the nprobe parameter to a larger value, such as 80, 100, 120, 140, or 160. The performance overhead incurred by increasing the value of the nprobe parameter is much less than that of adjusting the value of the reorder_factor parameter. However, we recommend that you do not set the nprobe parameter to an excessively large value.

You can also use the post_filter mode to add filter conditions to implement approximate queries.

SearchRequest searchRequest = new SearchRequest();
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

// vectorColumn is the name of the vector column.
Map<String, Object> queryBody = Map.of("knn", Map.of(vectorColumn, Map.of(
  "vector", vectors,
  "k", topK)));
searchSourceBuilder.query(QueryBuilders.wrapperQuery(new Gson().toJson(queryBody)));

// field1 >= 0
searchSourceBuilder.postFilter(QueryBuilders.rangeQuery("field1").gte(0));

searchRequest.source(searchSourceBuilder);
searchRequest.indices(index);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);

Common operations

  • Query all indexes and their data volumes.

    Request request = new Request("GET", "/_cat/indices?v");
    Response response = restClient.performRequest(request);
    String responseBody = EntityUtils.toString(response.getEntity());
    System.out.println(responseBody);
  • Query the data volume of a specific index.

    CountRequest countRequest = new CountRequest(index);
    CountResponse countResponse = client.count(countRequest, RequestOptions.DEFAULT);
    System.out.println(countResponse.getCount());
  • View the index creation information.

    GetIndexRequest getIndexRequest = new GetIndexRequest(index);
    
    GetIndexResponse getIndexResponse = client.indices().get(getIndexRequest, RequestOptions.DEFAULT);
    
    getIndexResponse.getMappings().forEach((k, v) -> System.out.println(k + " " + v.getSourceAsMap()));
    getIndexResponse.getSettings().forEach((k, v) -> System.out.println(k + " " + v));
  • Delete an entire index.

    DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(index);
    AcknowledgedResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
    System.out.println("deleteIndexResponse: " + deleteIndexResponse.isAcknowledged());
  • Delete an index by query.

    DeleteByQueryRequest deleteByQueryRequest = new DeleteByQueryRequest(index);
    deleteByQueryRequest.setQuery(QueryBuilders.termQuery("field1", "1"));
    BulkByScrollResponse bulkByScrollResponse = client.deleteByQuery(deleteByQueryRequest, RequestOptions.DEFAULT);
    System.out.println(bulkByScrollResponse.getTotal());