Basic features

更新时间:
复制 MD 格式

The Lindorm vector engine supports vector data retrieval and hybrid search across scalar, vector, and full-text fields. It is compatible with the Elasticsearch protocol. This topic shows how to connect to and use the vector engine with the curl command.

Prerequisites

Algorithms

Choose a vector index for your business scenario based on the features and supported data volume of each algorithm.

Algorithm

Data volume

Resource usage

Features

Notes

flat

[0, 10,000)

Pure memory.

Brute-force search. Simple to use and suitable for small datasets.

Search performance decreases as the data volume increases.

hnsw

[10,000, 1,000,000)

Pure memory, high resource usage.

Online indexing. Suitable for medium-sized datasets and relatively easy to use.

CPU usage depends on the number_of_shards parameter, which is typically set to the number of vector engine nodes. If you have a large number of indexes and each index contains a small amount of data, set number_of_shards to 1.

hnswq

[10,000, 1,000,000)

Supports datasets with tens of millions of vectors in high-performance scenarios.

Pure memory.

Lindorm-developed next-generation layered HNSW algorithm:

Layer 1 coarse-grained ranking layer: Compresses vectors using SQ8 + PCA for dimensionality reduction and quantization.

Layer 2 fine-grained ranking layer: Loads full-precision vectors to rerank a small number of top candidates. This approach significantly improves search throughput without compromising recall.

  • The amount of data written to build the index must be greater than the vector dimension.

  • Both the search engine and vector engine must be V3.10.15 or later. Contact Lindorm technical support (DingTalk ID: s0s3eg3) to upgrade.

ivfpq

More than 1,000,000

Disk indexing. By default, the 1:8 compression ratio reduces memory usage to one-eighth of the original data size.

Offline indexing. You need to write a specific amount of data before building an index. This method is cost-effective and suitable for large datasets.

Before you build an index, ensure that sufficient data has been written. The number of records must be greater than 256 and exceed 30 times the value of nlist.

Trigger the index build after the offline data import is complete. You can then perform kNN queries and write operations.

Note

For more information about the nlist parameter, see Parameters.

ivfbq

More than 1,000,000

Disk indexing. You can adjust memory usage by tuning the exbits parameter.

For offline indexing, the ivf + rabitq compression algorithm is currently more suitable for datasets with vector dimensions between 512 and 1024, and provides better performance than ivfpq.

Both the search engine and vector engine must be V3.10.4 or later. Contact Lindorm technical support (DingTalk ID: s0s3eg3) to upgrade.

Create a vector index

Create a vector index where vector1 is a vector column and field1 is a regular column. The vector column and its related parameters must be explicitly specified in the mappings structure when you create the index.

Hnsw index

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_test?pretty"  -d '
{
 "settings" : {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "dimension": 3,
        "method": {
          "name": "hnsw", 
          "space_type": "cosinesimil"
       }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Hnswq index

Important

To build an HNSWQ index, you must first write an amount of data that is greater than the vector dimension.

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_hnswq_test?pretty"  -d '
{
 "settings" : {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "dimension": 3,
        "method": {
          "name": "hnswq", 
          "space_type": "cosinesimil"
       }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Ivfpq index

Important

When creating an IVFPQ index, you must write a sufficient amount of data before building the index. You can run queries only after the index is built.

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_ivfpq_test?pretty"  -d '
{
  "settings": {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "dimension": 3,
        "method": {
          "name": "ivfpq",
          "space_type": "cosinesimil",
          "parameters": {
            "nlist": 10000
          }
        }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Ivfbq index

Important

When creating an IVFBQ index, you must write a sufficient amount of data before building the index. You can run queries only after the index is built.

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_ivfbq_test?pretty"  -d '
{
  "settings": {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "dimension": 3,  
        "method": {
          "name": "ivfbq",
          "space_type": "cosinesimil",
          "parameters": {
            "nlist": 10000
          }
        }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Sparse vector index

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_sparse_test?pretty"  -d '
{
 "settings" : {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "method": {
          "name": "sparse_hnsw"
       }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Index with multiple vector fields

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/mvector_test?pretty"  -d '
{
  "settings": {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "dimension": 3,
        "method": {
          "name": "ivfpq",
          "space_type": "cosinesimil",
          "parameters": {
            "nlist": 10000
          }
        }
      },
      "vector2": {
        "type": "knn_vector",
        "dimension": 3,
        "method": {
          "name": "hnsw", 
          "space_type": "cosinesimil"
       }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Sparse inverted index

Inverted indexes provide a higher recall rate than HNSW graph indexes but have lower search performance. In practical applications, you can adjust the threshold_factor parameter (threshold adjustment factor) as the primary method to balance the recall rate and query throughput (QPS).

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_sparse_inverted_test?pretty"  -d '
{
 "settings" : {
    "index": {
      "number_of_shards": 2
    }
  },
  "mappings": {
    "properties": {
      "vector1": {
        "type": "knn_vector",
        "method": {
          "name": "sparse_inverted_index"
       }
      },
      "field1": {
        "type": "long"
      }
    }
  }
}'

Parameters

Connection parameters

Parameter

Required

Example

Description

URL

Yes

ld-bp106782jm96****-proxy-search-vpc.lindorm.aliyuncs.com:30070

The Elasticsearch-compatible connection URL for LindormSearch. For details on how to obtain this URL, see Elasticsearch-compatible addresses.

username

Yes

xltest

The username and password used to access the vector engine.

To obtain the default username and password, in the left navigation bar of the console, select Database Connections and click the Search Engine tab. The credentials are provided on the Search Engine tab.

password

Yes

test

Vector column parameters

General parameters

Parameter

Required

Description

type

Yes

The type of the index column. For vector columns, this value is fixed to knn_vector.

dimension

Yes

The number of vector dimensions. Valid values: 1 to 131,072.

data_type

No

The vector's data type. The following data types are supported:

  • float

  • float16

  • sparse_vector (This type is supported only for a sparse vector index.)

method.name

Yes

The vector index algorithm. Valid values:

  • flat

  • hnsw

  • hnswq

  • ivfpq

  • ivfbq

  • sparse_hnsw (This algorithm is supported only for a sparse vector index.)

  • sparse_inverted_index (sparse vector based on an inverted index)

method.space_type

No

The vector distance algorithm. Valid values:

  • l2 (default): Euclidean distance.

  • cosinesimil: cosine distance.

  • innerproduct: inner product distance.

Hnsw algorithm parameters

Parameter

Required

Description

method.parameters.m

No

The maximum number of outgoing edges for each layer of the graph.

Value range: [1,100]. The default value is 24.

method.parameters.ef_construction

No

The length of the dynamic list during index building.

Valid range: [1, 1000]. The default value is 500.

Hnswq algorithm parameters

Parameter

Required

Description

method.parameters.m

No

The maximum number of outgoing edges for each layer of the graph.

Valid range: [1,100]. The default value is 24.

method.parameters.ef_construction

No

The length of the dynamic list during index building.

Value range: [1,1000]. The default value is 500.

method.parameters.level_1

No

The first-level quantization algorithm. Valid values:

  • FP32: 32-bit floating-point

  • FP16: 16-bit half-precision floating-point

The default value is FP16.

method.parameters.level_2

No

The second-level quantization algorithm. Valid values:

  • NONE

  • FP16: 16-bit half-precision floating-point, with minor precision loss.

  • SQ8U: 8-bit unsigned integer scalar quantization, providing a balance between precision and performance.

  • SQ4U: 4-bit unsigned integer scalar quantization, with minimal memory usage.

The default value is SQ8U.

method.parameters.pca_level

No

Specifies whether to perform PCA dimension reduction on vectors. Valid values:

  • NONE

  • level2: Performs PCA only on level_2.

  • all: Performs PCA on both level_1 and level_2.

The default value is level2.

Ivfpq algorithm parameters

Parameter

Required

Description

method.parameters.m

No

The number of subspaces in quantization. The valid range of values is [2, 131072]. The default value is dimension.

Important

When creating an IVFPQ index, this parameter's value must match the value of the dimension parameter.

method.parameters.nlist

No

The number of cluster centroids.

The valid range is [2, 1000000]. The default value is 10000.

method.parameters.centroids_use_hnsw

No

Specifies whether to use the HNSW algorithm when searching for cluster centroids.

Valid values:

  • true (default)

  • false

method.parameters.centroids_hnsw_m

No

If HNSW is used to search for cluster centroids, this parameter specifies the maximum number of outgoing edges for each layer of the graph.

The valid range is from 1 to 100. The default value is 32.

method.parameters.centroids_hnsw_ef_construct

No

If HNSW is used to search for cluster centroids, this parameter specifies the length of the dynamic list during index building.

Value range: [1,1000]. The default value is 500.

method.parameters.centroids_hnsw_ef_search

No

If HNSW is used to search for cluster centroids, this parameter specifies the length of the dynamic list during a query.

Value range: [1,1000]. The default value is 200.

Ivfbq algorithm parameters

Parameter

Required

Description

method.parameters.exbits

No

Specifies the number of extra bits to represent the quantized vector.

The value range is [0, 2, 3, 4, 6, 7, 8]. The default value is 0.

When you use Rabitq quantization, the larger the exbits value, the higher the recall rate and memory usage. To balance the recall rate and memory usage, you can set the value to 2.

method.parameters.nlist

No

The number of cluster centroids.

Valid values: [2, 1000000]. The default value is 10000.

method.parameters.centroids_use_hnsw

No

Specifies whether to use HNSW when searching for cluster centroids.

Valid values:

  • true (default)

  • false

method.parameters.centroids_hnsw_m

No

If HNSW is used to search for cluster centroids, this parameter specifies the maximum number of outgoing edges for each layer of the graph.

Valid range: [1, 100]. The default value is 32.

method.parameters.centroids_hnsw_ef_construct

No

If HNSW is used to search for cluster centroids, this parameter specifies the length of the dynamic list during index building.

The valid range is [1, 1000]. The default value is 500.

method.parameters.centroids_hnsw_ef_search

No

If HNSW is used to search for cluster centroids, this parameter specifies the length of the dynamic list during a query.

Valid range: [1,1000]. The default value is 200.

Assume that the vector index is named vector_test. The result is as follows:

{"acknowledged":true,"shards_acknowledged":true,"index":"vector_test"}

Write data

You can write data to an index containing vector fields just as you would to a regular index. Vector data is written as a float array, such as [1.2, 1.3, 1.4].

Single write

curl -u <username>:<password> -H 'Content-Type: application/json' -XPOST "http://<URL>/<index_name>/_doc/1?pretty"  -d '
{"field1": 1, "vector1": [1.2, 1.3, 1.4]}'

For an index named vector_test, the following response is returned:

{"_index":"vector_test","_type":"_doc","_id":"1","_version":1,"result":"created","_shards":{"total":1,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1}

Bulk write

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/_bulk?pretty"  -d '
{ "index" : { "_index" : "vector_test", "_id" : "2" } }
{ "field1" : 1, "vector1": [2.2, 2.3, 2.4]}
{ "index" : { "_index" : "vector_test", "_id" : "3" } }
{ "field1" : 2, "vector1": [1.2, 1.3, 4.4]}
{ "delete" : { "_index" : "vector_test", "_id" : "2" } }
{ "update" : {"_id" : "1", "_index" : "vector_test"} }
{ "doc" : {"field1" : 3, "vector1": [2.2, 3.3, 4.4]} }
'

Insert

The operation fails if a document with the same ID already exists.

curl -u <username>:<password> -H 'Content-Type: application/json' -XPOST "http://<URL>/_bulk?pretty"  -d '
{ "create" : { "_index" : "vector_test", "_id" : "1" } }
{ "field1" : 1, "vector1": [2.2, 2.3, 2.4]}
{ "create" : { "_index" : "vector_test", "_id" : "2" } }
{ "field1" : 2, "vector1": [1.2, 1.3, 4.4]}
'

Overwrite

If a document with the specified ID does not exist, a new one is created. If a document with the same ID already exists, the existing document is overwritten. For example, if you write a document with only a vector field, and a subsequent write for the same ID contains only a scalar field, the original vector field is deleted.

curl -u <username>:<password> -H 'Content-Type: application/json' -XPOST "http://<URL>/_bulk?pretty"  -d '
{ "index" : { "_index" : "vector_test", "_id" : "3" } }
{ "field1" : 1, "vector1": [2.2, 2.3, 2.4]}
{ "index" : { "_index" : "vector_test", "_id" : "4" } }
{ "field1" : 2, "vector1": [1.2, 1.3, 4.4]}
'

Sparse vector write

The write method is the same as previously described, but the format of the vector1 field is different. Two formats are supported: JSON STRING and JSON Object. The JSON STRING format provides better performance, while the JSON Object format is more user-friendly.

JSON string

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_sparse_test/_doc/1?pretty"  -d '{
  "field1": 2, 
  "vector1": "{\"indices\": [10, 14, 16], \"values\": [0.5, 0.5, 0.2]}"
}'

JSON object

curl -u <username>:<password> -H 'Content-Type: application/json' -XPUT "http://<URL>/vector_sparse_test/_doc/1?pretty"  -d '{
  "field1": 1, 
  "vector1": {"indices": [10, 12, 16], "values": [0.5, 0.5, 0.2]}
}'

Index building

Important
  • Before you trigger an index build for ivfpq or ivfbq indexes, ensure that the data volume is sufficient. The data volume must be greater than 256 records and more than 30 times the value of the nlist parameter.

  • When you trigger an index build for an hnswq index, ensure that the data volume is greater than the vector dimension.

  • After you manually build the index, you can write and query data normally. You do not need to build the index again.

Trigger index building

curl -u <username>:<password> -H 'Content-Type: application/json' -XPOST "http://<URL>/_plugins/_vector/index/build"  -d '
{
  "indexName": "vector_ivfpq_test",
  "fieldName": "vector1",
  "removeOldIndex": "true"
}'

Parameters

Parameter

Required

Description

indexName

Yes

The index name. Example: vector_ivfpq_test.

fieldName

Yes

The field to index. Example: vector1.

removeOldIndex

Yes

Specifies whether to delete the old index when building a new one. Valid values:

  • true: Deletes the old index data when the build is triggered. You can perform kNN queries only after the new index is built.

    Important

    For production environments, we recommend setting this parameter to true.

  • false (default): Retains the old index. This may affect search performance.

A successful request returns the following response:

{
  "payload": ["default_vector_ivfpq_test_vector1"]
}

The returned result is the taskId generated by index building.

View the index status

Use the following command to check the index building status.

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/_plugins/_vector/index/tasks"  -d '{
  "indexName": "vector_ivfpq_test",
  "fieldName": "vector1",
  "taskIds": "[\"default_vector_ivfpq_test_vector1\"]"
}'

The taskIds parameter is the taskId generated when a build is triggered. You can specify an empty array, for example, "taskIds": "[]". The effect is the same as when a value is specified for taskIds.

A successful request returns the following response:

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

The stage field indicates the building status. Valid values are START, TRAIN, BUILDING, ABORT, FINISH, and FAIL.

Note

You can call the /index/abort API operation to stop an index build. After the build is stopped, its status changes to ABORT.

Stop an index build

This operation stops the index building process. You cannot stop an index build that is in the FINISH state.

curl -u <username>:<password> -H 'Content-Type: application/json' -XPOST "http://<URL>/_plugins/_vector/index/tasks/abort"  -d '{
  "indexName": "vector_ivfpq_test",
  "fieldName": "vector1",
  "taskIds": "[\"default_vector_ivfpq_test_vector1\"]"
}'

Query data

Pure vector search

Use the knn query structure to perform a pure vector search.

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.3, 3.3, 4.4],
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"min_score": "0.01"}}
}'

Parameters

Parameter structure

Parameter

Required

Description

knn

vector

Yes

The query vector.

k

Yes

The number of nearest neighbors to return.

Important

For pure vector searches, set the size and k parameters to the same value.

ext

lvector.min_score

No

The similarity threshold. Only results with a score greater than this value are returned. The returned vector score ranges from 0 to 1.

Valid values: [0, +inf). Default value: 0.

lvector.filter_type

No

The integrated query mode. Valid values:

  • pre_filter: Filters structured data before the vector search.

  • post_filter: Performs the vector search and then filters the results based on structured data.

  • efficient_filter: The system automatically selects pre_filter or post_filter based on an internal cost estimation.

    Important

    Requires Lindorm Search 3.9.10 or later.

Default value: efficient_filter.

lvector.ef_search

No

The length of the dynamic list during a query. This parameter applies only to the HNSW algorithm.

Valid values: [1, 1000]. Default value: 100.

lvector.nprobe

No

The number of cluster units to query. A larger value improves the recall rate but decreases search performance. Adjust this value to meet your recall rate requirements.

Valid values: [1, method.parameters.nlist]. No default value is provided.

Important

This parameter is applicable only to the IVFPQ and IVFBQ algorithms.

lvector.reorder_factor

No

Performs reordering by using original vectors. The IVFPQ algorithm calculates distances from quantized vectors, which can cause precision loss. To improve accuracy, enable reordering on the original vectors. The number of results to reorder is k * reorder_factor. This process improves recall but increases performance overhead.

Valid values: [1, 200]. Default value: 2.

Important
  • This parameter is applicable only to the IVFPQ and IVFBQ algorithms.

  • If k is small, set this parameter to 5. If k is greater than 100, set it to 1.

lvector.client_refactor

No

Specifies whether to perform reordering at a higher system layer instead of within each shard. This can improve performance. Valid values:

  • true: Yes.

  • false (default): No.

lvector. k_expand_scope

No

For an approximate search in efficient_filter mode, if the system selects the post_filter strategy, this parameter is used instead of the k parameter to expand the search scope. The default value is 1000.

The following example shows a query on the HNSW index vector_test and the corresponding output:

View output

{
  "took" : 30,
  "timed_out" : false,
  "terminated_early" : false,
  "num_reduce_phases" : 0,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "vector_test",
        "_id" : "2",
        "_score" : 1.0
      },
      {
        "_index" : "vector_test",
        "_id" : "1",
        "_score" : 0.25
      },
      {
        "_index" : "vector_test",
        "_id" : "3",
        "_score" : 0.14285715
      }
    ]
  }
}

Return specific fields

To return only specific fields in the query results, specify "_source": ["field1", "field2"] . To return all non-vector fields, use "_source": true. The following example shows how to query the vector_test index:

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/vector_test/_search?pretty"  -d '
{
  "size": 10,
  "_source": ["field1"],
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.2, 2.3, 2.4],
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"min_score": "0.01"}}
}'

The query returns the following response:

View output

{
  "took" : 35,
  "timed_out" : false,
  "terminated_early" : false,
  "num_reduce_phases" : 0,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "vector_test",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "field1" : 1
        }
      },
      {
        "_index" : "vector_test",
        "_id" : "1",
        "_score" : 0.25,
        "_source" : {
          "field1" : 1
        }
      },
      {
        "_index" : "vector_test",
        "_id" : "3",
        "_score" : 0.14285715,
        "_source" : {
          "field1" : 2
        }
      }
    ]
  }
}

HNSW and HNSWQ query

The following example shows how to query the HNSW index vector_test:

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/vector_test/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.2, 2.3, 2.4],
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"ef_search": "100"}}
}'

IVFPQ and IVFBQ query

The IVFPQ and IVFBQ algorithms use the same query parameters. The following example shows how to query the IVFPQ index vector_ivfpq_test:

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/vector_ivfpq_test/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.2, 2.3, 2.4],
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"nprobe": "60", "reorder_factor": "2"}}
}'
Important
  • If k is large (for example, greater than 100), set reorder_factor to 1.

  • When nlist is 10000, you can first set nprobe to 60 and check the search results. To further improve the recall rate, you can increase nprobe to 80, 100, 120, 140, or 160. The performance overhead from increasing nprobe is much lower than that from increasing reorder_factor, but do not set nprobe to an excessively large value.

Sparse vector query

The query method is the same, but the vector1 field format differs. Sparse vectors support two formats: JSON String for better performance and JSON Object for user-friendliness.

Json string

The following example shows how to query the sparse vector index vector_sparse_test:

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/vector_sparse_test/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": "{\"indices\": [10, 45, 16], \"values\": [0.5, 0.5, 0.2]}",
        "k": 10
      }
    }
  }
}'

Json object

The following example shows how to query the sparse vector index vector_sparse_test:

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/vector_sparse_test/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": {"indices": [10, 45, 16], "values": [0.5, 0.5, 0.2]},
        "k": 10
      }
    }
  }
}'

Sparse vector inverted index query

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://ld-t631ui****.lindorm.aliyuncs.com:30070/vector_sparse_inverted_test/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": "{\"indices\": [10, 45, 16], \"values\": [0.5, 0.5, 0.2]}",
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"search_algo": "max_score", "threshold_factor":"1.5"}}
}'

The following are the ext.lvector parameters for sparse vector inverted index queries. For information about other parameters, see Parameter descriptions.

Parameter

Description

Default value

threshold_factor

A scaling factor for the threshold that controls how many inverted lists are accessed. You can adjust this value to balance the recall rate and QPS. A larger value increases QPS but can slightly reduce the recall rate. A value of 1 ensures 100% recall. The value must be greater than or equal to 1.

1

search_algo

The query algorithm. Valid values:

  • max_score: Skips low-value terms. This is suitable for long queries or large k values.

  • wand: Uses dynamic pruning to skip low-scoring documents and accelerate retrieval. This is suitable for short queries or small k values.

max_score

Integrated query

Combine a vector search with filters on regular columns to get more relevant results. In practice, post-filtering often yields better similarity search results.

Pre-filtering approximate search

To filter structured data before the vector search, add a filter clause to the knn query and set the filter_type parameter to pre_filter.

Note

You can filter a maximum of 10,000 structured data records.

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.3, 3.3, 4.4],
        "filter": {
          "range": {
            "field1": {
              "gte": 0
            }
          }
        },
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"filter_type": "pre_filter"}}
}'

Post-filtering approximate search

To filter results after the vector search, add a filter clause to the knn query and set the filter_type parameter to post_filter.

Note

When you use post-filtering, you may need to increase k to ensure enough vector results are retrieved for filtering.

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.3, 3.3, 4.4],
        "filter": {
          "range": {
            "field1": {
              "gte": 0
            }
          }
        },
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"filter_type": "post_filter"}}
}'

When you use post-filtering for an approximate search, you must increase k. If you use the IVFPQ algorithm, you must also adjust reorder_factor. For example:

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<ivfpq_index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.2, 2.3, 2.4],
        "filter": {
          "range": {
            "field1": {
              "gte": 0
            }
          }
        },
        "k": 1000
      }
    }
  },
  "ext": {"lvector": {"filter_type": "post_filter","nprobe": "60", "reorder_factor": "1"}}
}'
Important
  • In post-filtering scenarios, you can increase k up to 10,000, with a maximum of 20,000, to keep the processing latency within hundreds of milliseconds. If k is large, set reorder_factor to 1.

  • With an nlist of 10000, start by setting nprobe to 60 and check the search results. If the results are not ideal, you can increase nprobe to 80, 100, 120, 140, or 160. Increasing nprobe incurs less performance overhead than increasing reorder_factor, but do not set nprobe to an excessively large value.

You can also add filter conditions using the post_filter clause to perform an approximate search with post-filtering.

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.3, 3.3, 4.4],
        "k": 10
      }
    }
  },
  "post_filter": {
    "range": {
      "field1": {
        "gte": 0
      }
    }
  }
}'

Efficient filtering approximate search

Important

Requires Lindorm Search 3.9.10 or later. For more information, see Perform a minor version update. If your Lindorm Search version is earlier than 3.9.10 but the console shows that you are using the latest version, contact Lindorm technical support (DingTalk ID: s0s3eg3).

For an approximate search, you can explicitly choose a filtering strategy by setting the filter_type parameter to pre_filter or post_filter. To let the system choose automatically, set the filter_type parameter to efficient_filter, which uses an internal cost estimation to select either the pre_filter or post_filter strategy.

HNSW and HNSWQ

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.2, 2.3, 2.4],
        "filter": {
          "range": {
            "field1": {
              "gte": 0
            }
          }
        },
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"filter_type": "efficient_filter", "ef_search":"
100", "k_expand_scope": "2000"}}
}'
Note
  • We recommend that you set the size and k parameters to the same value.

  • When you use an HNSW index, you can increase ef_search to improve the recall rate, but this may decrease performance. For example, if the length of the dynamic list is 100 and a high recall rate is required, you can set ef_search to 200.

  • k_expand_scope: If the system selects the post_filter mode, the k_expand_scope parameter is used instead of the k parameter.

IVFPQ and IVFBQ

curl -u <username>:<password> -H 'Content-Type: application/json' -XGET "http://<URL>/<index_name>/_search?pretty"  -d '
{
  "size": 10,
  "query": {
    "knn": {
      "vector1": {
        "vector": [2.2, 2.3, 2.4],
        "filter": {
          "range": {
            "field1": {
              "gte": 0
            }
          }
        },
        "k": 10
      }
    }
  },
  "ext": {"lvector": {"filter_type": "efficient_filter","nprobe": "80", "reorder_factor": "2","client_refactor":"true", "k_expand_scope": "2000"}}
}'
Note
  • We recommend that you set the size and k parameters to the same value.

  • With an nlist of 10000, start by setting nprobe to 60. If the search results are not ideal, increase nprobe to 80, 100, 120, 140, or 160. Increasing nprobe incurs less performance overhead than increasing reorder_factor, but avoid setting nprobe to an excessively large value.

  • k_expand_scope: If the system selects the post_filter mode, the k_expand_scope parameter is used instead of the k parameter.

Attribute filter syntax

The filter clause adds filter conditions and accepts standard OpenSearch query DSL.

"filter": {
  "range": {
    "field1": {
      "gte": 0
    }
  }
}

Multiple AND conditions

  • Use bool.must to require that all conditions in the list are met.

    "filter": {
      "bool": {
        "must": [{
          "range": {
            "field1": {
              "gt": 2
            }
          }
        },
        {
          "term": {
            "field2": "flag2"
          }
        }]
      }
    }
  • Use bool.filter to require that all conditions in the list are met. This clause only considers whether a document matches and does not affect the score. This method is more efficient for vector searches and is recommended.

    "filter": {
      "bool": {
        "filter": [{
          "range": {
            "field1": {
              "gt": 2
            }
          }
        },
        {
          "term": {
            "field2": "flag2"
          }
        }]
      }
    }

Multiple OR conditions

"filter": {
  "bool": {
    "should": [{
      "range": {
        "field1": {
          "gt": 2
        }
      }
    },
    {
      "term": {
        "field2": "flag2"
      }
    }]
  }
}

Common operations

This section covers basic index operations, including querying, deleting documents, and deleting an index. The following examples use the HNSW index vector_test.

  • Query all indexes and their data volumes.

    curl -u <username>:<password> -XGET "http://<URL>/_cat/indices?v"

    Sample output:

    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
  • Query the data volume of a specific index. For example, the following command queries the vector_test index.

    curl -u <username>:<password> -XGET "http://<URL>/vector_test/_count?pretty"

    Sample output:

    {
      "count" : 2,
      "_shards" : {
        "total" : 2,
        "successful" : 2,
        "skipped" : 0,
        "failed" : 0
      }
    }
  • View the index creation information.

    curl -u <username>:<password> -XGET "http://<URL>/vector_test?pretty"

    Sample output:

    Show output

    {
      "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"
            }
          }
        }
      }
    }
  • Delete an entire index.

    curl -u <username>:<password>  -XDELETE "http://<URL>/vector_test"
  • Delete documents by query.

    curl -u <username>:<password> -H 'Content-Type: application/json' -XPOST "http://<URL>/vector_test/_delete_by_query"  -d '
    {
      "query": {
        "term": {
          "field1": 1
        }
      }
    }'