Conduct a Query With Iterators
This topic describes how to search and query data with iterators.
Before an iterator is introduced, one common way of querying or searching a large dataset in Milvus is to use offset
and limit
parameters in combination, which specify the starting position and the maximum number of items to return respectively. However, this method may lead to performance issues as the offset and limit continuously increase, potentially imposing a substantial memory burden on Milvus servers. For more information about offset
and limit
, see Conduct a Vector Similarity Search.
For that to happen the database will need to perform an inefficient full scan every time you request a pagination. This means that if there are 100,000,000 search results and you request an offset
of 50,000,000, the system will need to fetch all those records (which will not even be needed), cache them in memory, sort according to vector similarity and primary key and afterwards only retrieve the 20 results specified in limit
.
To address the performance issue, an alternative is to use an iterator, which is an object that allows you to use expr
to filter scalar fields and then iterate over a sequence of search or query results. Using an iterator has some advantages:
- It simplifies the code and eliminates the need for manual configuration of
offset
andlimit
. - It’s more efficient and consistent, as it filters fields by Boolean expressions first and fetches data on demand.
Milvus provides two types of iterators, query iterator and search iterator, for vector query and similarity search, respectively. The following examples show how to search and query data with iterators.
Load collection
All search and query operations within Milvus are executed in memory. Load the collection to memory before conducting a vector similarity search.
from pymilvus import Collection
collection = Collection("book") # Get an existing collection.
collection.load()
await milvusClient.loadCollection({
collection_name: "book",
});
err := milvusClient.LoadCollection(
context.Background(), // ctx
"book", // CollectionName
false // async
)
if err != nil {
log.Fatal("failed to load collection:", err.Error())
}
milvusClient.loadCollection(
LoadCollectionParam.newBuilder()
.withCollectionName("book")
.build()
);
load -c book
curl -X 'POST' \
'http://localhost:9091/api/v1/collection/load' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"collection_name": "book"
}'
Query with iterator
The following example uses expr
to define a Boolean expression that looks for results where the number of pages in a book is between 600 and 700 inclusive, and then creates a query iterator along with output fields for the book ID and authors. The batch_size
parameter is set to 10, meaning that every page returned will consist of 10 entities. And the limit
parameter is set to 100, which means that the query will return a maximum of 100 results totally. Note that iterator guarantees that no repeated results will be returned so if there are not enough entities matched input expr, the iterator will return empty page and the whole iteration should terminate.
In the code, the query iterator’s next()
method is called repeatedly to retrieve each page of results. If the length of the returned results is zero, it means that there are no more pages to retrieve, so the loop is exited and the iterator is closed by using close()
. Otherwise, the results are printed to the console, with each result showing the book ID and authors.
# filter books with the number of pages ranging from 600 to 700
expr = "600 <= num_pages <= 700"
# return `bookID` and `authors`
output_fields=[bookID, authors]
# return 10 results per page and 100 results totally
batch_size = 10
limit = 100
# create a query iterator
query_iterator = collection.query_iterator(batch_size, limit, expr, output_fields)
while True:
# turn to the next page
res = query_iterator.next()
if len(res) == 0:
print("query iteration finished, close")
# close the iterator
query_iterator.close()
break
for i in range(len(res)):
print(res[i])
Search with iterator
The following example creates a search iterator using the generated vectors, search parameters, and output fields for the book ID and authors.
The batch_size
parameter is also set to 10, which means that the search will return exact 5 entities per page, except for the final page.
And the parameter limit
is set to 100, meaning that the iterator will return 100 entities in total at most.
Note that iterator guarantees that no repeated results will be returned so if there are not enough entities, the iterator will return empty page and the whole iteration should terminate.
Regarding the radius
and range_filter
parameters, search_iterators will ensure the returned entities are restricted
in the range defined by these two parameters. More information is available in Within Range.
vectors_to_search = rng.random((SEARCH_NQ, DIM))
search_params = {
"metric_type": "L2",
"params": {"nprobe": 10, "radius": 1.0, "range_filter": 0.7},
}
# create a search iterator
search_iterator = collection.search_iterator(
data=vectors_to_search,
anns_field="vector_field",
param=search_params,
batch_size=10,
limit=100,
expr="600 <= num_pages <= 700",
output_fields=["bookID", "authors"]
)
while True:
# turn to the next page
res = search_iterator.next()
if len(res[0]) == 0:
print("search iteration finished, close")
# close the iterator
search_iterator.close()
break
for i in range(len(res[0])):
print(res[0][i])
Parameters
The following table describes the parameters for searching or querying data with iterators.
Parameter | Description |
---|---|
expr | Boolean expression used to filter attributes. Find more expression details in Boolean Expression Rules. |
data | The list of vectors to search with. |
anns_field | Name of the vector field. |
param | Search parameters specific to the index. Find more expression details in Conduct a Vector Similarity Search. |
batch_size | Number of entities to return per page. |
limit | Number of results to return totally in this iteration process. |
radius | Angle where the vector with the least similarity resides. Find more expression details in Within Range. |
range_filter | The filter used to filter a part of entities. Find more expression details in Within Range. |
output_fields | Name of the field to return. Milvus supports returning the vector field. |
What’s next
Explore API references for Milvus SDKs: