Data Operations - Query & Search
This guide covers querying and searching data in Milvus collections.
Query Operations
Section titled “Query Operations”Query retrieves entities based on filter expressions.
Basic Query
Section titled “Basic Query”Query entities with a filter expression:
const results = await client.query({ collection_name: 'my_collection', expr: 'age > 25', output_fields: ['id', 'vector', 'text'],});Query by IDs
Section titled “Query by IDs”Query specific entities by their IDs:
const results = await client.query({ collection_name: 'my_collection', ids: [1, 2, 3, 4, 5], output_fields: ['id', 'vector', 'text'],});Query with Limit, Offset, and Ordering
Section titled “Query with Limit, Offset, and Ordering”const results = await client.query({ collection_name: 'my_collection', expr: 'age > 25', output_fields: ['id', 'text', 'price'], limit: 10, offset: 0, order_by_fields: [{ field: 'price', order: 'desc' }],});order_by_fields can be a string, an array of strings, or an array of { field, order } objects:
await client.query({ collection_name: 'my_collection', expr: 'age > 25', output_fields: ['id', 'price', 'rating'], order_by_fields: 'price:asc,rating:desc',});
await client.query({ collection_name: 'my_collection', expr: 'age > 25', output_fields: ['id', 'price', 'rating'], order_by: ['price:asc', { field: 'rating', order: 'desc' }], // alias});Query Specific Partitions
Section titled “Query Specific Partitions”const results = await client.query({ collection_name: 'my_collection', expr: 'age > 25', partition_names: ['partition_1', 'partition_2'], output_fields: ['id', 'text'],});Query Iterator
Section titled “Query Iterator”Iterate through large result sets:
const iterator = await client.queryIterator({ collection_name: 'my_collection', expr: 'age > 25', output_fields: ['id', 'text'], batch_size: 100,});
while (true) { const batch = await iterator.next(); if (batch.done) break;
console.log('Batch:', batch.value);}Get Operation
Section titled “Get Operation”Get entities by IDs (simpler than query):
const results = await client.get({ collection_name: 'my_collection', ids: [1, 2, 3], output_fields: ['id', 'vector', 'text'],});Count Operation
Section titled “Count Operation”Count entities matching a filter:
const result = await client.count({ collection_name: 'my_collection', expr: 'age > 25',});
console.log('Count:', result.data);Search Operations
Section titled “Search Operations”Search finds similar vectors using distance metrics.
Basic Search
Section titled “Basic Search”const results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], // Search vector limit: 10, output_fields: ['id', 'text'],});Search by ID
Section titled “Search by ID”perform a vector similarity search using the vectors associated with exact entity IDs:
const results = await client.search({ collection_name: 'my_collection', ids: [1, 2, 3], // primary keys limit: 10, output_fields: ['id', 'text'],});[!NOTE]
- When
idsare provided, thedataparameter (dummy vectors) is not required.- The provided
idsmust match the collection’s Primary Key type (Int64orVarChar).- For collections with multiple vector fields, explicitly specifying
anns_fieldis recommended (and required to disambiguate).
Search Multiple Vectors
Section titled “Search Multiple Vectors”const results = await client.search({ collection_name: 'my_collection', data: [ [0.1, 0.2, 0.3, 0.4], [0.5, 0.6, 0.7, 0.8], ], limit: 10, output_fields: ['id', 'text'],});Search with Filter
Section titled “Search with Filter”Combine vector search with scalar filters:
const results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], expr: 'age > 25 AND category == "tech"', limit: 10, output_fields: ['id', 'text', 'age'],});Search with Ordering
Section titled “Search with Ordering”Sort search results by scalar fields after vector retrieval:
const results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], limit: 10, output_fields: ['id', 'price', 'rating'], order_by_fields: [ { field: 'price', order: 'asc' }, { field: 'rating', order: 'desc' }, ],});You can also pass order_by_fields as a string, for example 'price:asc,rating:desc'. If you also pass params.order_by_fields, the top-level order_by_fields value takes precedence.
Search Parameters
Section titled “Search Parameters”Configure search parameters for different index types:
// For IVF indexesconst results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], params: { nprobe: 64, // Number of clusters to search }, limit: 10,});
// For HNSW indexesconst results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], params: { ef: 100, // Search width }, limit: 10,});Search Specific Partitions
Section titled “Search Specific Partitions”const results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], partition_names: ['partition_1'], limit: 10,});Search Iterator
Section titled “Search Iterator”Iterate through large search results:
const iterator = await client.searchIterator({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], expr: 'age > 25', limit: 1000, batch_size: 100,});
while (true) { const batch = await iterator.next(); if (batch.done) break;
console.log('Batch:', batch.value);}Hybrid Search
Section titled “Hybrid Search”Search with multiple vector fields:
const results = await client.hybridSearch({ collection_name: 'my_collection', reqs: [ { data: [[0.1, 0.2, 0.3, 0.4]], anns_field: 'text_vector', param: { nprobe: 64 }, limit: 10, }, { data: [[0.5, 0.6, 0.7, 0.8]], anns_field: 'image_vector', param: { nprobe: 64 }, limit: 10, }, ], ranker: 'rrf', // Reciprocal Rank Fusion limit: 10, output_fields: ['id', 'text'],});Filter Expressions
Section titled “Filter Expressions”Filter expressions use Milvus expression syntax:
Comparison Operators
Section titled “Comparison Operators”'age > 25';'age >= 25';'age < 25';'age <= 25';'age == 25';'age != 25';Logical Operators
Section titled “Logical Operators”'age > 25 AND category == "tech"';'age > 25 OR age < 18';'NOT (age > 25)';In Operator
Section titled “In Operator”'id in [1, 2, 3, 4, 5]';'category in ["tech", "science"]';String Operations
Section titled “String Operations”'text like "milvus%"';'text like "%database%"';JSON Field Access
Section titled “JSON Field Access”'metadata.category == "tech"';'metadata.tags[0] == "ai"';Search Results
Section titled “Search Results”Search results include:
const results = await client.search({ collection_name: 'my_collection', data: [[0.1, 0.2, 0.3, 0.4]], limit: 10,});
results.results.forEach((result) => { console.log('ID:', result.id); console.log('Distance:', result.distance); console.log('Score:', result.score); console.log('Entity:', result.entity);});Element-Level Offsets Milvus 3.0
Section titled “Element-Level Offsets Milvus 3.0”For element-level retrieval, Milvus can return the matching element offsets for array or multi-vector fields. The SDK flattens element_indices into result rows and adds an offset property that identifies the matched element within the source field.
const results = await client.search({ collection_name: 'chunked_docs', data: [ [ /* query vector */ ], ], anns_field: 'chunk_embeddings', limit: 10, output_fields: ['doc_id', 'title'],});
results.results.forEach((row) => { console.log('Document:', row.doc_id); console.log('Matched element offset:', row.offset);});Grouped search responses can also include group_by_field_values, which the SDK exposes on each result row:
results.results.forEach((row) => { console.log('Score:', row.score); console.log('Group by values:', row.group_by_field_values);});Output Fields
Section titled “Output Fields”Specify which fields to return:
// Return specific fieldsoutput_fields: ['id', 'text', 'age'];
// Return all fieldsoutput_fields: ['*'];
// Return vector fieldsoutput_fields: ['id', 'vector'];Performance Optimization
Section titled “Performance Optimization”Search Parameters Tuning
Section titled “Search Parameters Tuning”IVF indexes:
nprobe: Higher values improve recall but slower (typical: 16-256)
HNSW indexes:
ef: Higher values improve recall but slower (typical: 50-200)
Batch Search
Section titled “Batch Search”Search multiple vectors efficiently:
const results = await client.search({ collection_name: 'my_collection', data: [ [ /* vector 1 */ ], [ /* vector 2 */ ], [ /* vector 3 */ ], ], limit: 10,});Pre-load Collections
Section titled “Pre-load Collections”Load collections before searching:
await client.loadCollectionSync({ collection_name: 'my_collection',});
// Now searchconst results = await client.search({ /* ... */});Best Practices
Section titled “Best Practices”- Use appropriate limits: Set reasonable limits to avoid large result sets
- Filter before search: Use filter expressions to narrow down results
- Tune search parameters: Adjust nprobe/ef based on your recall/performance needs
- Use iterators: For large result sets, use query/search iterators
- Load collections: Always load collections before searching
- Batch operations: Search multiple vectors in one call when possible
Complete Example
Section titled “Complete Example”import { MilvusClient, DataType } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({ address: 'localhost:19530',});
await client.connectPromise;
// Load collectionawait client.loadCollectionSync({ collection_name: 'my_collection',});
// Queryconst queryResults = await client.query({ collection_name: 'my_collection', expr: 'age > 25', output_fields: ['id', 'text', 'age'], limit: 10,});
console.log('Query results:', queryResults.data);
// Searchconst searchResults = await client.search({ collection_name: 'my_collection', data: [Array.from({ length: 128 }, () => Math.random())], expr: 'age > 25', limit: 10, output_fields: ['id', 'text'], params: { nprobe: 64, },});
console.log('Search results:', searchResults.results);Next Steps
Section titled “Next Steps”- Learn about Delete Operations
- Explore Data Management
- Check out Best Practices