Performing Vector Similarity Search

This topic introduces how to use Milvus to search for entities.

In Milvus, vector similarity search calculates the distance between the query vector and the vectors in the collection (using a specified similarity measure) and returns the most similar results. You can execute mixed searching by specifying a boolean expression to filter scalar or primary key fields.

The following example demonstrates how to perform vector similarity search on a dataset containing 2000 rows of data, including book ID (primary key), word count (scalar field), and book synopsis (vector field), to simulate searching for specific books based on their vectorized descriptions. Milvus will return the most similar results based on the query vector and search parameters you define.

Loading the Collection

All search and query operations within Milvus are executed in memory. Before performing vector similarity search, load the collection into memory.

from pymilvus import Collection
collection = Collection("book")      # Get the existing collection.
collection.load()

Preparing the Search Parameters

Prepare the corresponding parameters for your search scenario. The following example defines the parameters that the search will use to compute the distance using Euclidean distance and retrieve vectors from the ten nearest clusters built by the IVF_FLAT index.

search_params = {
    "metric_type": "L2",
    "offset": 5,
    "ignore_growing": False,
    "params": {"nprobe": 10}
}
Parameter Description
metric_type The method used to measure the distance between vectors during the search. It should be the same as the method specified during the index building process. Refer to similarity measures for more information.
offset The number of entities to skip during the search. The sum of this value and the limit of the search method should be less than 16384. For example, if you want to query the 9th and 10th nearest neighbors of the query vector, set limit to 2 and offset to 8.
ignore_growing Whether to ignore growing segments during the similarity search. The default value is False, indicating that the search includes growing segments.
params Search parameters specific to the specified index type. Refer to vector index for more information. Possible options include: - nprobe indicates the number of clustering units to search. This parameter is only available when setting index_type to IVF_FLAT, IVF_SQ8, or IVF_PQ. The value should be less than the nlist value specified during the index building process. - ef indicates the search range. This parameter is only available when setting index_type to HNSW. The value should be between top_k and 32768. - radius indicates the angle where vectors with the lowest similarity are located. - range_filter indicates the filter used to filter vector field values whose similarity to the query vector falls within a specific range.

Performing Vector Search

Use Milvus for vector search. To search within a specific partition, specify a list of partition names.

Milvus supports setting a consistency level for searches. The example in this topic sets the consistency level to "Strong". You can also set the consistency level to "Bounded", "Session", or "Eventually". For more information on the four consistency levels in Milvus, see Consistency.

results = collection.search(
    data=[[0.1, 0.2]], 
    anns_field="book_intro", 
    param=search_params,
    limit=10,
    expr=None,
    output_fields=['title'],
    consistency_level="Strong"
)

results[0].ids

results[0].distances

hit = results[0][0]
hit.entity.get('title')
Parameter Description
data Vectors used for search.
anns_field Name of the field to be searched.
param Search parameters specific to the index. For more information, see Vector Index.
limit Number of results to return. This value, plus the offset in param, should be less than 16,384.
expr Boolean expression for filtering properties. For more information, see Boolean Expression Rules.
output_fields (optional) Names of the fields to return. Vector fields are not currently supported.
consistency_level (optional) Consistency level for the search.

Check the primary key values and distances of the most similar vectors.

results[0].ids
results[0].distances

Once the search is complete, release the loaded collection in Milvus to reduce memory consumption.

collection.release()

Limitations

Feature Maximum Limit
Collection name length 255 characters
Number of partitions in a collection 4,096
Number of fields in a collection 256
Number of shards in a collection 256
Vector dimension 32,768
Top K 16,384
Input vectors 16,384

Performing Mixed Search

Mixed search is essentially a vector search with attribute filtering. By specifying a boolean expression used to filter scalar fields or primary key fields, searches can be limited under specific conditions.

The following example demonstrates how to perform mixed search based on the regular vector search. Let's say you want to search for certain books based on vectorized summaries, but you only want to search within a specific word count range. Then, you can specify a boolean expression in the search parameters to filter the word_count field. Milvus will only search for similar vectors within the entities that match the expression.

By specifying a boolean expression, you can filter scalar fields of entities during vector search. The following example limits the search scope to vectors within the specified word_count value range.

You can also use dynamic fields in the filtering expression and use output fields in the search request. For example, refer to the dynamic pattern.

search_param = {
  "data": [[0.1, 0.2]],
  "anns_field": "book_intro",
  "param": {"metric_type": "L2", "params": {"nprobe": 10}, "offset": 0},
  "limit": 10,
  "expr": "word_count <= 11000",
}
res = collection.search(**search_param)

Check the returned results.

assert len(res) == 1
hits = res[0]
assert len(hits) == 2
print(f"- Total hits: {len(hits)}, hits ids: {hits.ids} ")
print(f"- Top1 hit id: {hits[0].id}, distance: {hits[0].distance}, score: {hits[0].score} ")

Performing Range Search

Range search is a method of filtering search results based on the distance between the query vector and the vector field values. Different distance metrics can be used to measure the distance.

When performing range search, Milvus first conducts vector similarity search. Then, it executes vector filtering based on the specified distance conditions and returns the vectors whose distance falls within a specific range.

The following example demonstrates how to perform range search based on regular vector search.

Loading the Collection

All search and query operations in Milvus are executed in memory. Before performing vector similarity search, the collection needs to be loaded into memory.

from pymilvus import Collection
collection = Collection("book")      # Get an existing collection
collection.load()

Configuring Vector Filtering Ranges

In comparison to regular vector search, range search in Milvus is controlled by introducing two new parameters, radius and range_filter, to obtain the desired search results within a specific search range.

The radius specifies the minimum angle at which the vectors are considered similar. An optional range_filter can be utilized in conjunction with the radius to filter the vector field values based on the similarity to the query vector within a specific range. Both the radius and range_filter parameters have a data type of FLOAT. Setting these two parameters effectively balances the accuracy and efficiency of the search.

Typically, similarity is measured by the distance between the vector field value and the query vector. The selection of different distance metrics will have a significant impact on the configuration of radius and range_filter.

For instance, in the case of L2 distance, the search results must be filtered based on the vector field values with a distance less than radius. This is because in L2 distance, smaller distances indicate greater similarity. With this knowledge, if you want to filter out some of the most similar vectors, you can specify an effective range_filter value that is less than radius.

search_params = {
    "metric_type": "L2",
    "params": {
        "radius": 10.0,
        "range_filter" : 5.0
    }
}

In the case of IP distance, the scenario is different. With IP distance, a larger distance signifies greater similarity. Therefore, in contrast to L2 distance, the values of radius and range_filter in IP distance are opposite. In other words, when using range_filter to filter out some of the most similar vectors based on IP distance, the effective range_filter value must be greater than radius, and the distance of resulting vectors should be greater than radius but less than or equal to range_filter.

search_params = {
    "metric_type": "IP",
    "params": {
        "radius": 0.8,
        "range_filter" : 1.0
    }
}

Performing Range Search

By specifying radius and range_filter based on the distance measurement type, you can define the range of result vectors to be returned.

Perform range search on similarity within the range of 5.0 and 10.0 based on L2 distance:

search_param = {
  "data": [[0.1, 0.2]], # Query vector
  "anns_field": "book_intro", # Field to be searched
  "param": { "metric_type": "L2", "params": { "nprobe": 10, "radius": 10.0, "range_filter" : 5.0 }, "offset": 0 },
  "limit": 2,
  "output_fields": ["int64", "float"]  # Fields to be returned
}

res = collection.search(**search_param)

Perform range search on similarity within the range of 1.0 and 0.8 based on IP distance:

search_param = {
  "data": [[0.1, 0.2]], # Query vector
  "anns_field": "book_intro", # Field to be searched
  "param": {"metric_type": "IP", "params": { "nprobe": 10, "radius": 0.8, "range_filter" : 1.0 }, "offset": 0 },
  "limit": 2,
  "output_fields": ["int64", "float"]  # Fields to be returned
}

res = collection.search(**search_param)

Summary

In Milvus, range search can return vector results that are similar within the specified distance range. This functionality is enabled by specifying radius and range_filter in the search parameters. The table below summarizes the configuration of these two parameters for different distance measurement types.

Distance Measurement Type Configuration
L2 and other distances range_filter <= distance < radius
IP and cosine distances radius < distance <= range_filter