The Official Milvus node.js sdk(client)
198
stars
1,071
commits
TypeScript
primary language
Sep 8, 2026
updated
Official Node.js SDK for Milvus vector database. Provides gRPC and HTTP clients for vector similarity search, metadata filtering, and full collection/index/user management.
Package: @zilliz/milvus2-sdk-node | Node.js: v18+ | License: Apache-2.0
Documentation: Guides & API reference · 3.0.5 release notes
The latest documented release is 3.0.5. New features include Bloom/Roaring membership helpers, client telemetry (enabled by default), and six additional index enum values. SDK 3.0.4 also added Text fields and asynchronous function-field backfill.
npm install @zilliz/milvus2-sdk-node
# or
yarn add @zilliz/milvus2-sdk-node
| Milvus version | SDK version | Install command |
|---|---|---|
| v3.0.0+ | 3.0.x | yarn add @zilliz/milvus2-sdk-node@3 |
| v2.6.0+ | 2.6.x | yarn add @zilliz/milvus2-sdk-node@2.6 |
| v2.5.0+ | v2.5.0 | yarn add @zilliz/milvus2-sdk-node@2.5.12 |
| v2.4.0+ | v2.4.9 | yarn add @zilliz/milvus2-sdk-node@2.4.9 |
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
// Local Milvus
const client = new MilvusClient({ address: 'localhost:19530' });
// With authentication
const client = new MilvusClient({
address: 'localhost:19530',
username: 'root',
password: 'milvus',
});
// Zilliz Cloud
const client = new MilvusClient({
address: 'https://your-endpoint.zillizcloud.com',
token: 'your-api-key',
});
// Wait for connection to be ready
await client.connectPromise;
import { MilvusClient, DataType, MetricType } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({ address: 'localhost:19530' });
// 1. Create collection with schema
await client.createCollection({
collection_name: 'my_collection',
fields: [
{
name: 'id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: true,
},
{ name: 'text', data_type: DataType.VarChar, max_length: 512 },
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
],
index_params: [
{
field_name: 'vector',
index_type: 'HNSW',
metric_type: MetricType.COSINE,
params: { M: 16, efConstruction: 256 },
},
],
enable_dynamic_field: true,
});
// 2. Load into memory (required before search/query)
await client.loadCollectionSync({ collection_name: 'my_collection' });
// 3. Insert data
await client.insert({
collection_name: 'my_collection',
data: [
{ vector: Array(128).fill(0.1), text: 'doc1' },
{ vector: Array(128).fill(0.2), text: 'doc2' },
],
});
// 4. Search
const results = await client.search({
collection_name: 'my_collection',
data: [Array(128).fill(0.1)],
limit: 10,
consistency_level: 'Strong', // Include the rows just inserted
output_fields: ['text'],
});
console.log(results.results);
// Main client
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
// HTTP client (for environments without gRPC support)
import { HttpClient } from '@zilliz/milvus2-sdk-node';
// Enums and constants
import {
DataType,
MetricType,
IndexType,
ConsistencyLevelEnum,
ErrorCode,
} from '@zilliz/milvus2-sdk-node';
// Bulk writer for large-scale imports
import { BulkWriter } from '@zilliz/milvus2-sdk-node';
new MilvusClient({
address: string; // Required. "host:port" or "https://host:port"
token?: string; // Auth token (username:password or API key)
username?: string; // Username for auth
password?: string; // Password for auth
ssl?: boolean; // Enable SSL/TLS
database?: string; // Default database name
timeout?: number | string; // Request timeout in milliseconds
maxRetries?: number; // Max retry attempts (default: 3)
retryDelay?: number; // Retry delay in ms (default: 10)
logLevel?: string; // 'debug' | 'info' | 'warn' | 'error'
telemetry?: TelemetryConfig; // Heartbeat metrics; enabled by default
trace?: boolean; // Enable OpenTelemetry tracing
tls?: { // TLS certificate configuration
rootCertPath?: string;
privateKeyPath?: string;
certChainPath?: string;
serverName?: string;
skipCertCheck?: boolean;
};
pool?: { // Connection pool (generic-pool options)
max?: number; // Max connections (default: 10)
min?: number; // Min connections (default: 2)
};
});
Insert rows into a collection.
await client.insert({
collection_name: string;
data: Record<string, any>[]; // Array of row objects
partition_name?: string;
});
// Returns: { succ_index: number[], err_index: number[], IDs: string[] | number[], ... }
Insert or update rows (matched by primary key).
await client.upsert({
collection_name: string;
data: Record<string, any>[];
partition_name?: string;
partial_update?: boolean;
field_ops?: Array<{
field_name: string;
op: 'REPLACE' | 'ARRAY_APPEND' | 'ARRAY_REMOVE';
}>;
});
Partial array upsert can append to or remove from existing Array fields:
import { FieldPartialUpdateOpType } from '@zilliz/milvus2-sdk-node';
await client.upsert({
collection_name: 'articles',
data: [{ id: 1, tags: ['featured'] }],
field_ops: [
{ field_name: 'tags', op: FieldPartialUpdateOpType.ARRAY_APPEND },
],
});
Delete rows by filter expression or primary key IDs.
// By filter
await client.delete({
collection_name: 'articles',
filter: 'age > 18',
});
// By IDs
await client.delete({
collection_name: 'articles',
ids: [1, 2, 3],
});
Vector similarity search.
const results = await client.search({
collection_name: string;
data?: number[][] | number[]; // Query vector(s), not required when ids is provided
ids?: (string | number)[]; // Primary key IDs for Search By PK
limit?: number; // Top-K results (default: 100)
output_fields?: string[]; // Fields to return
filter?: string; // Scalar filter expression
metric_type?: MetricType; // Distance metric
params?: { // Index-specific search params
ef?: number; // HNSW ef (search width)
nprobe?: number; // IVF nprobe
radius?: number; // Range search radius
range_filter?: number; // Range search filter
};
consistency_level?: ConsistencyLevelEnum;
partition_names?: string[];
group_by_field?: string; // Group results by field
});
// Returns: { results: [{ id, score, ...output_fields }], ... }
Search by primary key IDs without providing query vectors:
const results = await client.search({
collection_name: 'articles',
ids: [1, 2, 3],
output_fields: ['title', 'category'],
});
Search aggregation supports bucket metrics, top hits, and nested buckets.
const results = await client.search({
collection_name: 'products',
data: [0.1, 0.2, 0.3, 0.4],
output_fields: ['category', 'brand', 'price'],
search_aggregation: {
fields: ['category'],
size: 5,
metrics: {
item_count: { op: 'count', field_name: '*' },
avg_price: { op: 'avg', field_name: 'price' },
},
order: [{ key: 'avg_price', direction: 'desc' }],
top_hits: {
size: 2,
sort: [{ field_name: 'price', direction: 'asc' }],
},
sub_aggregation: {
fields: ['brand'],
size: 3,
},
},
});
// A single query vector returns AggregationBucket[].
// Multiple query vectors return AggregationBucket[][].
console.log(results.agg_buckets);
Query rows with scalar filter expression.
const results = await client.query({
collection_name: string;
filter: string; // Boolean expression, e.g. 'age > 18 AND status == "active"'
output_fields?: string[]; // Fields to return (default: all)
limit?: number;
offset?: number;
group_by_fields?: string[]; // Scalar fields used to group aggregation results
consistency_level?: ConsistencyLevelEnum;
partition_names?: string[];
});
// Returns: { data: Record<string, any>[] }
Aggregation functions are specified in output_fields. The supported functions
are count, min, max, sum, and avg.
const results = await client.query({
collection_name: 'sales',
filter: 'price > 0',
group_by_fields: ['category'],
output_fields: [
'category',
'count(price)',
'min(price)',
'max(price)',
'sum(price)',
'avg(price)',
],
});
Get rows by primary key IDs.
const results = await client.get({
collection_name: string;
ids: (string | number)[];
output_fields?: string[];
});
Count rows matching a filter.
const result = await client.count({
collection_name: string;
filter?: string;
});
// Returns: { data: number }
Paginated vector search using async iterator.
const iterator = await client.searchIterator({
collection_name: string;
data: number[];
batchSize: number;
limit: number;
output_fields?: string[];
filter?: string;
expr?: string;
});
for await (const batch of iterator) {
console.log(batch); // Array of results per batch
}
Paginated query using async iterator.
const iterator = await client.queryIterator({
collection_name: string;
filter?: string;
batchSize: number;
limit: number;
output_fields?: string[];
expr?: string;
});
for await (const batch of iterator) {
console.log(batch);
}
Multi-vector search combining results from multiple vector fields with reranking.
const results = await client.hybridSearch({
collection_name: string;
rerank: WeightedReranker | RRFReranker; // Reranking strategy
requests: Array<{
data: number[][];
anns_field: string;
params?: Record<string, any>;
limit?: number;
filter?: string;
}>;
limit: number;
output_fields?: string[];
});
await client.createCollection({
collection_name: string;
fields: FieldType[]; // Define schema fields
index_params?: CreateIndexParam[]; // Create indexes at collection creation time
enable_dynamic_field?: boolean; // Allow inserting fields not in schema
consistency_level?: ConsistencyLevelEnum;
num_partitions?: number;
});
// Note: call loadCollection() after creation before search/query
await client.hasCollection({ collection_name }); // { value: boolean }
await client.describeCollection({ collection_name }); // Schema, fields, properties
await client.batchDescribeCollections({ collection_names: string[] }); // Describe multiple collections
await client.showCollections(); // List all collections
await client.loadCollection({ collection_name }); // Load into memory
await client.releaseCollection({ collection_name }); // Release from memory
await client.refreshLoad({ collection_name }); // Refresh loaded collection
await client.dropCollection({ collection_name }); // Delete collection
await client.renameCollection({ collection_name, new_collection_name });
await client.truncateCollection({ collection_name }); // Clear all data
await client.getLoadState({ collection_name }); // Loading status
await client.getCollectionStatistics({ collection_name });
await client.alterCollectionProperties({ collection_name, properties });
await client.alterCollectionFieldProperties({ collection_name, field_name, properties });
await client.dropCollectionProperties({ collection_name, delete_keys: string[] });
await client.addCollectionFunction({ collection_name, functions });
await client.dropCollectionFunction({ collection_name, functions });
// Create index
await client.createIndex({
collection_name: string;
field_name: string;
index_type?: IndexType; // Default: AUTOINDEX
metric_type?: MetricType; // Default: COSINE
params?: Record<string, any>; // e.g. { M: 16, efConstruction: 256 }
index_name?: string;
});
// Other index operations
await client.describeIndex({ collection_name, field_name? });
await client.listIndexes({ collection_name });
await client.getIndexStatistics({ collection_name, index_name? });
await client.dropIndex({ collection_name, field_name, index_name? });
await client.getIndexState({ collection_name, field_name? });
await client.getIndexBuildProgress({ collection_name, field_name? });
await client.alterIndexProperties({ collection_name, index_name, properties });
await client.dropIndexProperties({ collection_name, index_name, delete_keys: string[] });
await client.createPartition({ collection_name, partition_name });
await client.hasPartition({ collection_name, partition_name });
await client.listPartitions({ collection_name });
await client.loadPartitions({ collection_name, partition_names: string[] });
await client.releasePartitions({ collection_name, partition_names: string[] });
await client.dropPartition({ collection_name, partition_name });
await client.createDatabase({ db_name });
await client.listDatabases();
await client.describeDatabase({ db_name });
await client.alterDatabaseProperties({ db_name, properties });
await client.dropDatabaseProperties({ db_name, delete_keys: string[] });
await client.dropDatabase({ db_name });
// Users
await client.createUser({ username, password });
await client.updateUser({ username, oldPassword, newPassword });
await client.deleteUser({ username });
await client.listUsers();
// Roles
await client.createRole({ roleName });
await client.dropRole({ roleName });
await client.listRoles();
await client.addUserToRole({ username, roleName });
await client.removeUserFromRole({ username, roleName });
// Privileges
await client.grantPrivilege({ roleName, object, objectName, privilegeName });
await client.revokePrivilege({ roleName, object, objectName, privilegeName });
await client.listGrants({ roleName });
// V2 privilege API
await client.grantPrivilegeV2({ role, privilege, collection_name, db_name });
await client.revokePrivilegeV2({ role, privilege, collection_name, db_name });
await client.createAlias({ collection_name, alias });
await client.dropAlias({ alias });
await client.alterAlias({ collection_name, alias });
await client.describeAlias({ alias });
await client.listAliases({ collection_name });
await client.createResourceGroup({ resource_group, config });
await client.listResourceGroups();
await client.describeResourceGroup({ resource_group });
await client.dropResourceGroup({ resource_group });
await client.transferReplica({
source_resource_group,
target_resource_group,
collection_name,
num_replica,
});
import { BulkWriter, DataType } from '@zilliz/milvus2-sdk-node';
const writer = new BulkWriter({
schema: {
fields: [
{ name: 'id', data_type: DataType.Int64, is_primary_key: true },
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
{ name: 'title', data_type: DataType.VarChar, max_length: 256 },
],
},
format: 'parquet', // 'json' or 'parquet'
localPath: './bulk_data',
chunkSize: 128 * 1024 * 1024, // 128 MB per file
});
// Append rows
for (const row of rows) {
await writer.append(row);
}
// Finalize and get file paths
const batchFiles = await writer.close();
// batchFiles: [['./bulk_data/batch_0/1.parquet'], ...]
// Trigger bulk import (files must be on Milvus-accessible storage)
await client.bulkInsert({ collection_name, files: ['data.json'] });
// Check import status
await client.getImportState({ taskId });
await client.listImportTasks({ collection_name });
await client.flush({ collection_names: string[] });
await client.flushSync({ collection_names: string[] }); // Wait for completion
await client.flushAll(); // Flush all collections
await client.flushAllSync(); // Flush all and wait for completion
await client.compact({ collection_name });
await client.getCompactionState({ compactionID });
await client.getVersion(); // Milvus server version
await client.checkHealth(); // Server health status
await client.reconnectToPrimary(); // Force reconnect to primary node
await client.runAnalyzer({ text, analyzer }); // Test text analyzer tokenization
| DataType enum | TypeScript value | Notes |
|---|---|---|
DataType.Bool | boolean | |
DataType.Int8 | number | |
DataType.Int16 | number | |
DataType.Int32 | number | |
DataType.Int64 | number | string | Use string for values > 2^53 |
DataType.Float | number | |
DataType.Double | number | |
DataType.VarChar | string | Requires max_length |
DataType.JSON | object | |
DataType.Array | any[] | Requires element_type, max_capacity |
| DataType enum | Data format | Field param |
|---|---|---|
DataType.FloatVector | number[] | dim: number |
DataType.BinaryVector | number[] (uint8 bytes) | dim: number |
DataType.Float16Vector | number[] | dim: number |
DataType.BFloat16Vector | number[] | dim: number |
DataType.Int8Vector | number[] | dim: number |
DataType.SparseFloatVector | Record<number, number> or array | no dim needed |
interface FieldType {
name: string;
data_type: DataType;
is_primary_key?: boolean;
autoID?: boolean;
dim?: number; // Required for vector types
max_length?: number; // Required for VarChar
element_type?: DataType; // Required for Array
max_capacity?: number; // Required for Array
default_value?: any;
is_partition_key?: boolean;
enable_analyzer?: boolean; // For full-text search
analyzer_params?: object;
}
MetricType.L2; // Euclidean distance (smaller = more similar)
MetricType.IP; // Inner product (larger = more similar)
MetricType.COSINE; // Cosine similarity (larger = more similar)
MetricType.HAMMING; // Hamming distance (binary vectors)
MetricType.JACCARD; // Jaccard distance (binary vectors)
MetricType.BM25; // BM25 relevance (sparse/text)
IndexType.AUTOINDEX; // Automatic selection (recommended)
IndexType.HNSW; // High recall, in-memory
IndexType.IVF_FLAT; // Balanced speed/recall
IndexType.IVF_SQ8; // Compressed IVF
IndexType.IVF_PQ; // High compression IVF
IndexType.FLAT; // Brute-force (exact)
IndexType.DISKANN; // On-disk index
IndexType.BIN_FLAT; // Binary brute-force
IndexType.BIN_IVF_FLAT; // Binary IVF
IndexType.SPARSE_INVERTED_INDEX; // Sparse vectors
IndexType.SPARSE_WAND; // Sparse vectors (WAND)
ConsistencyLevelEnum.Strong; // Read-after-write guarantee
ConsistencyLevelEnum.Session; // Session-level consistency
ConsistencyLevelEnum.Bounded; // Bounded staleness
ConsistencyLevelEnum.Eventually; // Best performance
ErrorCode.SUCCESS; // Operation succeeded
ErrorCode.UnexpectedError; // Internal error
ErrorCode.CollectionNotExists; // Collection not found
ErrorCode.IllegalArgument; // Invalid argument
ErrorCode.RateLimit; // Rate limited
Used in search({ filter }), query({ filter }), delete({ filter }).
# Comparison
age > 18
price <= 99.9
status == "active"
name != "test"
# Logical operators
age > 18 AND status == "active"
price < 10 OR price > 100
NOT (status == "deleted")
# IN operator
id IN [1, 2, 3]
category IN ["books", "music"]
# String matching
title LIKE "hello%" # Starts with "hello"
title LIKE "%world" # Ends with "world"
# Array operations
ARRAY_CONTAINS(tags, "ai")
ARRAY_LENGTH(tags) > 3
# JSON field access
metadata["key"] == "value"
metadata["nested"]["field"] > 10
# Template expressions (parameterized)
await client.query({
collection_name: 'test',
filter: 'age > {min_age}',
filter_params: { min_age: 18 },
});
For environments where gRPC is not available (Cloudflare Workers, Vercel Edge, AWS Lambda).
import { HttpClient } from '@zilliz/milvus2-sdk-node';
const client = new HttpClient({
endpoint: 'localhost:19530', // or Zilliz Cloud endpoint
username: 'root', // optional
password: 'milvus', // optional
token: 'your-api-key', // optional (for Zilliz Cloud)
database: 'default', // optional
timeout: 60000, // optional, ms
});
// Same API surface as MilvusClient for data operations
await client.createCollection({ ... });
await client.insert({ ... });
await client.search({ ... });
await client.query({ ... });
import { ErrorCode } from '@zilliz/milvus2-sdk-node';
try {
const res = await client.createCollection({ ... });
if (res.error_code !== ErrorCode.SUCCESS) {
console.error('Milvus error:', res.reason);
}
} catch (err) {
console.error('Connection/transport error:', err.message);
}
const results = await client.search({
collection_name: 'products',
data: [queryVector],
limit: 20,
filter: 'category == "electronics" AND price < 500',
output_fields: ['name', 'price', 'category'],
});
// Enable dynamic fields on collection
await client.createCollection({
collection_name: 'flexible',
fields: [
{ name: 'id', data_type: DataType.Int64, is_primary_key: true, autoID: true },
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
],
enable_dynamic_field: true,
});
await client.loadCollection({ collection_name: 'flexible' });
// Insert with arbitrary fields — extra fields stored dynamically
await client.insert({
collection_name: 'flexible',
data: [
{ vector: [...], color: 'red', score: 0.95 },
{ vector: [...], color: 'blue', tags: ['a', 'b'] },
],
});
// Query dynamic fields
await client.query({
collection_name: 'flexible',
filter: 'color == "red"',
output_fields: ['color', 'score'],
});
await client.createCollection({
collection_name: 'docs',
fields: [
{
name: 'id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: true,
},
{ name: 'sparse_vector', data_type: DataType.SparseFloatVector },
],
});
await client.insert({
collection_name: 'docs',
data: [
{ sparse_vector: { 0: 0.5, 10: 0.3, 200: 0.8 } }, // dict format
{ sparse_vector: { 1: 0.1, 50: 0.9 } },
],
});
await client.search({
collection_name: 'docs',
data: [{ 0: 0.5, 10: 0.3 }],
anns_field: 'sparse_vector',
limit: 10,
});
await client.createCollection({
collection_name: 'multi_tenant',
fields: [
{
name: 'id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: true,
},
{
name: 'tenant',
data_type: DataType.VarChar,
max_length: 64,
is_partition_key: true,
},
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
],
num_partitions: 16,
});
// Milvus automatically routes by partition key
await client.search({
collection_name: 'multi_tenant',
data: [queryVector],
filter: 'tenant == "user_123"', // Scoped to partition
limit: 10,
});
For detailed guides on advanced features, visit the documentation:
TypeScript
99.9%
The Official Milvus node.js sdk(client)
198
stars
1,071
commits
TypeScript
primary language
Sep 8, 2026
updated
Official Node.js SDK for Milvus vector database. Provides gRPC and HTTP clients for vector similarity search, metadata filtering, and full collection/index/user management.
Package: @zilliz/milvus2-sdk-node | Node.js: v18+ | License: Apache-2.0
Documentation: Guides & API reference · 3.0.5 release notes
The latest documented release is 3.0.5. New features include Bloom/Roaring membership helpers, client telemetry (enabled by default), and six additional index enum values. SDK 3.0.4 also added Text fields and asynchronous function-field backfill.
npm install @zilliz/milvus2-sdk-node
# or
yarn add @zilliz/milvus2-sdk-node
| Milvus version | SDK version | Install command |
|---|---|---|
| v3.0.0+ | 3.0.x | yarn add @zilliz/milvus2-sdk-node@3 |
| v2.6.0+ | 2.6.x | yarn add @zilliz/milvus2-sdk-node@2.6 |
| v2.5.0+ | v2.5.0 | yarn add @zilliz/milvus2-sdk-node@2.5.12 |
| v2.4.0+ | v2.4.9 | yarn add @zilliz/milvus2-sdk-node@2.4.9 |
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
// Local Milvus
const client = new MilvusClient({ address: 'localhost:19530' });
// With authentication
const client = new MilvusClient({
address: 'localhost:19530',
username: 'root',
password: 'milvus',
});
// Zilliz Cloud
const client = new MilvusClient({
address: 'https://your-endpoint.zillizcloud.com',
token: 'your-api-key',
});
// Wait for connection to be ready
await client.connectPromise;
import { MilvusClient, DataType, MetricType } from '@zilliz/milvus2-sdk-node';
const client = new MilvusClient({ address: 'localhost:19530' });
// 1. Create collection with schema
await client.createCollection({
collection_name: 'my_collection',
fields: [
{
name: 'id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: true,
},
{ name: 'text', data_type: DataType.VarChar, max_length: 512 },
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
],
index_params: [
{
field_name: 'vector',
index_type: 'HNSW',
metric_type: MetricType.COSINE,
params: { M: 16, efConstruction: 256 },
},
],
enable_dynamic_field: true,
});
// 2. Load into memory (required before search/query)
await client.loadCollectionSync({ collection_name: 'my_collection' });
// 3. Insert data
await client.insert({
collection_name: 'my_collection',
data: [
{ vector: Array(128).fill(0.1), text: 'doc1' },
{ vector: Array(128).fill(0.2), text: 'doc2' },
],
});
// 4. Search
const results = await client.search({
collection_name: 'my_collection',
data: [Array(128).fill(0.1)],
limit: 10,
consistency_level: 'Strong', // Include the rows just inserted
output_fields: ['text'],
});
console.log(results.results);
// Main client
import { MilvusClient } from '@zilliz/milvus2-sdk-node';
// HTTP client (for environments without gRPC support)
import { HttpClient } from '@zilliz/milvus2-sdk-node';
// Enums and constants
import {
DataType,
MetricType,
IndexType,
ConsistencyLevelEnum,
ErrorCode,
} from '@zilliz/milvus2-sdk-node';
// Bulk writer for large-scale imports
import { BulkWriter } from '@zilliz/milvus2-sdk-node';
new MilvusClient({
address: string; // Required. "host:port" or "https://host:port"
token?: string; // Auth token (username:password or API key)
username?: string; // Username for auth
password?: string; // Password for auth
ssl?: boolean; // Enable SSL/TLS
database?: string; // Default database name
timeout?: number | string; // Request timeout in milliseconds
maxRetries?: number; // Max retry attempts (default: 3)
retryDelay?: number; // Retry delay in ms (default: 10)
logLevel?: string; // 'debug' | 'info' | 'warn' | 'error'
telemetry?: TelemetryConfig; // Heartbeat metrics; enabled by default
trace?: boolean; // Enable OpenTelemetry tracing
tls?: { // TLS certificate configuration
rootCertPath?: string;
privateKeyPath?: string;
certChainPath?: string;
serverName?: string;
skipCertCheck?: boolean;
};
pool?: { // Connection pool (generic-pool options)
max?: number; // Max connections (default: 10)
min?: number; // Min connections (default: 2)
};
});
Insert rows into a collection.
await client.insert({
collection_name: string;
data: Record<string, any>[]; // Array of row objects
partition_name?: string;
});
// Returns: { succ_index: number[], err_index: number[], IDs: string[] | number[], ... }
Insert or update rows (matched by primary key).
await client.upsert({
collection_name: string;
data: Record<string, any>[];
partition_name?: string;
partial_update?: boolean;
field_ops?: Array<{
field_name: string;
op: 'REPLACE' | 'ARRAY_APPEND' | 'ARRAY_REMOVE';
}>;
});
Partial array upsert can append to or remove from existing Array fields:
import { FieldPartialUpdateOpType } from '@zilliz/milvus2-sdk-node';
await client.upsert({
collection_name: 'articles',
data: [{ id: 1, tags: ['featured'] }],
field_ops: [
{ field_name: 'tags', op: FieldPartialUpdateOpType.ARRAY_APPEND },
],
});
Delete rows by filter expression or primary key IDs.
// By filter
await client.delete({
collection_name: 'articles',
filter: 'age > 18',
});
// By IDs
await client.delete({
collection_name: 'articles',
ids: [1, 2, 3],
});
Vector similarity search.
const results = await client.search({
collection_name: string;
data?: number[][] | number[]; // Query vector(s), not required when ids is provided
ids?: (string | number)[]; // Primary key IDs for Search By PK
limit?: number; // Top-K results (default: 100)
output_fields?: string[]; // Fields to return
filter?: string; // Scalar filter expression
metric_type?: MetricType; // Distance metric
params?: { // Index-specific search params
ef?: number; // HNSW ef (search width)
nprobe?: number; // IVF nprobe
radius?: number; // Range search radius
range_filter?: number; // Range search filter
};
consistency_level?: ConsistencyLevelEnum;
partition_names?: string[];
group_by_field?: string; // Group results by field
});
// Returns: { results: [{ id, score, ...output_fields }], ... }
Search by primary key IDs without providing query vectors:
const results = await client.search({
collection_name: 'articles',
ids: [1, 2, 3],
output_fields: ['title', 'category'],
});
Search aggregation supports bucket metrics, top hits, and nested buckets.
const results = await client.search({
collection_name: 'products',
data: [0.1, 0.2, 0.3, 0.4],
output_fields: ['category', 'brand', 'price'],
search_aggregation: {
fields: ['category'],
size: 5,
metrics: {
item_count: { op: 'count', field_name: '*' },
avg_price: { op: 'avg', field_name: 'price' },
},
order: [{ key: 'avg_price', direction: 'desc' }],
top_hits: {
size: 2,
sort: [{ field_name: 'price', direction: 'asc' }],
},
sub_aggregation: {
fields: ['brand'],
size: 3,
},
},
});
// A single query vector returns AggregationBucket[].
// Multiple query vectors return AggregationBucket[][].
console.log(results.agg_buckets);
Query rows with scalar filter expression.
const results = await client.query({
collection_name: string;
filter: string; // Boolean expression, e.g. 'age > 18 AND status == "active"'
output_fields?: string[]; // Fields to return (default: all)
limit?: number;
offset?: number;
group_by_fields?: string[]; // Scalar fields used to group aggregation results
consistency_level?: ConsistencyLevelEnum;
partition_names?: string[];
});
// Returns: { data: Record<string, any>[] }
Aggregation functions are specified in output_fields. The supported functions
are count, min, max, sum, and avg.
const results = await client.query({
collection_name: 'sales',
filter: 'price > 0',
group_by_fields: ['category'],
output_fields: [
'category',
'count(price)',
'min(price)',
'max(price)',
'sum(price)',
'avg(price)',
],
});
Get rows by primary key IDs.
const results = await client.get({
collection_name: string;
ids: (string | number)[];
output_fields?: string[];
});
Count rows matching a filter.
const result = await client.count({
collection_name: string;
filter?: string;
});
// Returns: { data: number }
Paginated vector search using async iterator.
const iterator = await client.searchIterator({
collection_name: string;
data: number[];
batchSize: number;
limit: number;
output_fields?: string[];
filter?: string;
expr?: string;
});
for await (const batch of iterator) {
console.log(batch); // Array of results per batch
}
Paginated query using async iterator.
const iterator = await client.queryIterator({
collection_name: string;
filter?: string;
batchSize: number;
limit: number;
output_fields?: string[];
expr?: string;
});
for await (const batch of iterator) {
console.log(batch);
}
Multi-vector search combining results from multiple vector fields with reranking.
const results = await client.hybridSearch({
collection_name: string;
rerank: WeightedReranker | RRFReranker; // Reranking strategy
requests: Array<{
data: number[][];
anns_field: string;
params?: Record<string, any>;
limit?: number;
filter?: string;
}>;
limit: number;
output_fields?: string[];
});
await client.createCollection({
collection_name: string;
fields: FieldType[]; // Define schema fields
index_params?: CreateIndexParam[]; // Create indexes at collection creation time
enable_dynamic_field?: boolean; // Allow inserting fields not in schema
consistency_level?: ConsistencyLevelEnum;
num_partitions?: number;
});
// Note: call loadCollection() after creation before search/query
await client.hasCollection({ collection_name }); // { value: boolean }
await client.describeCollection({ collection_name }); // Schema, fields, properties
await client.batchDescribeCollections({ collection_names: string[] }); // Describe multiple collections
await client.showCollections(); // List all collections
await client.loadCollection({ collection_name }); // Load into memory
await client.releaseCollection({ collection_name }); // Release from memory
await client.refreshLoad({ collection_name }); // Refresh loaded collection
await client.dropCollection({ collection_name }); // Delete collection
await client.renameCollection({ collection_name, new_collection_name });
await client.truncateCollection({ collection_name }); // Clear all data
await client.getLoadState({ collection_name }); // Loading status
await client.getCollectionStatistics({ collection_name });
await client.alterCollectionProperties({ collection_name, properties });
await client.alterCollectionFieldProperties({ collection_name, field_name, properties });
await client.dropCollectionProperties({ collection_name, delete_keys: string[] });
await client.addCollectionFunction({ collection_name, functions });
await client.dropCollectionFunction({ collection_name, functions });
// Create index
await client.createIndex({
collection_name: string;
field_name: string;
index_type?: IndexType; // Default: AUTOINDEX
metric_type?: MetricType; // Default: COSINE
params?: Record<string, any>; // e.g. { M: 16, efConstruction: 256 }
index_name?: string;
});
// Other index operations
await client.describeIndex({ collection_name, field_name? });
await client.listIndexes({ collection_name });
await client.getIndexStatistics({ collection_name, index_name? });
await client.dropIndex({ collection_name, field_name, index_name? });
await client.getIndexState({ collection_name, field_name? });
await client.getIndexBuildProgress({ collection_name, field_name? });
await client.alterIndexProperties({ collection_name, index_name, properties });
await client.dropIndexProperties({ collection_name, index_name, delete_keys: string[] });
await client.createPartition({ collection_name, partition_name });
await client.hasPartition({ collection_name, partition_name });
await client.listPartitions({ collection_name });
await client.loadPartitions({ collection_name, partition_names: string[] });
await client.releasePartitions({ collection_name, partition_names: string[] });
await client.dropPartition({ collection_name, partition_name });
await client.createDatabase({ db_name });
await client.listDatabases();
await client.describeDatabase({ db_name });
await client.alterDatabaseProperties({ db_name, properties });
await client.dropDatabaseProperties({ db_name, delete_keys: string[] });
await client.dropDatabase({ db_name });
// Users
await client.createUser({ username, password });
await client.updateUser({ username, oldPassword, newPassword });
await client.deleteUser({ username });
await client.listUsers();
// Roles
await client.createRole({ roleName });
await client.dropRole({ roleName });
await client.listRoles();
await client.addUserToRole({ username, roleName });
await client.removeUserFromRole({ username, roleName });
// Privileges
await client.grantPrivilege({ roleName, object, objectName, privilegeName });
await client.revokePrivilege({ roleName, object, objectName, privilegeName });
await client.listGrants({ roleName });
// V2 privilege API
await client.grantPrivilegeV2({ role, privilege, collection_name, db_name });
await client.revokePrivilegeV2({ role, privilege, collection_name, db_name });
await client.createAlias({ collection_name, alias });
await client.dropAlias({ alias });
await client.alterAlias({ collection_name, alias });
await client.describeAlias({ alias });
await client.listAliases({ collection_name });
await client.createResourceGroup({ resource_group, config });
await client.listResourceGroups();
await client.describeResourceGroup({ resource_group });
await client.dropResourceGroup({ resource_group });
await client.transferReplica({
source_resource_group,
target_resource_group,
collection_name,
num_replica,
});
import { BulkWriter, DataType } from '@zilliz/milvus2-sdk-node';
const writer = new BulkWriter({
schema: {
fields: [
{ name: 'id', data_type: DataType.Int64, is_primary_key: true },
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
{ name: 'title', data_type: DataType.VarChar, max_length: 256 },
],
},
format: 'parquet', // 'json' or 'parquet'
localPath: './bulk_data',
chunkSize: 128 * 1024 * 1024, // 128 MB per file
});
// Append rows
for (const row of rows) {
await writer.append(row);
}
// Finalize and get file paths
const batchFiles = await writer.close();
// batchFiles: [['./bulk_data/batch_0/1.parquet'], ...]
// Trigger bulk import (files must be on Milvus-accessible storage)
await client.bulkInsert({ collection_name, files: ['data.json'] });
// Check import status
await client.getImportState({ taskId });
await client.listImportTasks({ collection_name });
await client.flush({ collection_names: string[] });
await client.flushSync({ collection_names: string[] }); // Wait for completion
await client.flushAll(); // Flush all collections
await client.flushAllSync(); // Flush all and wait for completion
await client.compact({ collection_name });
await client.getCompactionState({ compactionID });
await client.getVersion(); // Milvus server version
await client.checkHealth(); // Server health status
await client.reconnectToPrimary(); // Force reconnect to primary node
await client.runAnalyzer({ text, analyzer }); // Test text analyzer tokenization
| DataType enum | TypeScript value | Notes |
|---|---|---|
DataType.Bool | boolean | |
DataType.Int8 | number | |
DataType.Int16 | number | |
DataType.Int32 | number | |
DataType.Int64 | number | string | Use string for values > 2^53 |
DataType.Float | number | |
DataType.Double | number | |
DataType.VarChar | string | Requires max_length |
DataType.JSON | object | |
DataType.Array | any[] | Requires element_type, max_capacity |
| DataType enum | Data format | Field param |
|---|---|---|
DataType.FloatVector | number[] | dim: number |
DataType.BinaryVector | number[] (uint8 bytes) | dim: number |
DataType.Float16Vector | number[] | dim: number |
DataType.BFloat16Vector | number[] | dim: number |
DataType.Int8Vector | number[] | dim: number |
DataType.SparseFloatVector | Record<number, number> or array | no dim needed |
interface FieldType {
name: string;
data_type: DataType;
is_primary_key?: boolean;
autoID?: boolean;
dim?: number; // Required for vector types
max_length?: number; // Required for VarChar
element_type?: DataType; // Required for Array
max_capacity?: number; // Required for Array
default_value?: any;
is_partition_key?: boolean;
enable_analyzer?: boolean; // For full-text search
analyzer_params?: object;
}
MetricType.L2; // Euclidean distance (smaller = more similar)
MetricType.IP; // Inner product (larger = more similar)
MetricType.COSINE; // Cosine similarity (larger = more similar)
MetricType.HAMMING; // Hamming distance (binary vectors)
MetricType.JACCARD; // Jaccard distance (binary vectors)
MetricType.BM25; // BM25 relevance (sparse/text)
IndexType.AUTOINDEX; // Automatic selection (recommended)
IndexType.HNSW; // High recall, in-memory
IndexType.IVF_FLAT; // Balanced speed/recall
IndexType.IVF_SQ8; // Compressed IVF
IndexType.IVF_PQ; // High compression IVF
IndexType.FLAT; // Brute-force (exact)
IndexType.DISKANN; // On-disk index
IndexType.BIN_FLAT; // Binary brute-force
IndexType.BIN_IVF_FLAT; // Binary IVF
IndexType.SPARSE_INVERTED_INDEX; // Sparse vectors
IndexType.SPARSE_WAND; // Sparse vectors (WAND)
ConsistencyLevelEnum.Strong; // Read-after-write guarantee
ConsistencyLevelEnum.Session; // Session-level consistency
ConsistencyLevelEnum.Bounded; // Bounded staleness
ConsistencyLevelEnum.Eventually; // Best performance
ErrorCode.SUCCESS; // Operation succeeded
ErrorCode.UnexpectedError; // Internal error
ErrorCode.CollectionNotExists; // Collection not found
ErrorCode.IllegalArgument; // Invalid argument
ErrorCode.RateLimit; // Rate limited
Used in search({ filter }), query({ filter }), delete({ filter }).
# Comparison
age > 18
price <= 99.9
status == "active"
name != "test"
# Logical operators
age > 18 AND status == "active"
price < 10 OR price > 100
NOT (status == "deleted")
# IN operator
id IN [1, 2, 3]
category IN ["books", "music"]
# String matching
title LIKE "hello%" # Starts with "hello"
title LIKE "%world" # Ends with "world"
# Array operations
ARRAY_CONTAINS(tags, "ai")
ARRAY_LENGTH(tags) > 3
# JSON field access
metadata["key"] == "value"
metadata["nested"]["field"] > 10
# Template expressions (parameterized)
await client.query({
collection_name: 'test',
filter: 'age > {min_age}',
filter_params: { min_age: 18 },
});
For environments where gRPC is not available (Cloudflare Workers, Vercel Edge, AWS Lambda).
import { HttpClient } from '@zilliz/milvus2-sdk-node';
const client = new HttpClient({
endpoint: 'localhost:19530', // or Zilliz Cloud endpoint
username: 'root', // optional
password: 'milvus', // optional
token: 'your-api-key', // optional (for Zilliz Cloud)
database: 'default', // optional
timeout: 60000, // optional, ms
});
// Same API surface as MilvusClient for data operations
await client.createCollection({ ... });
await client.insert({ ... });
await client.search({ ... });
await client.query({ ... });
import { ErrorCode } from '@zilliz/milvus2-sdk-node';
try {
const res = await client.createCollection({ ... });
if (res.error_code !== ErrorCode.SUCCESS) {
console.error('Milvus error:', res.reason);
}
} catch (err) {
console.error('Connection/transport error:', err.message);
}
const results = await client.search({
collection_name: 'products',
data: [queryVector],
limit: 20,
filter: 'category == "electronics" AND price < 500',
output_fields: ['name', 'price', 'category'],
});
// Enable dynamic fields on collection
await client.createCollection({
collection_name: 'flexible',
fields: [
{ name: 'id', data_type: DataType.Int64, is_primary_key: true, autoID: true },
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
],
enable_dynamic_field: true,
});
await client.loadCollection({ collection_name: 'flexible' });
// Insert with arbitrary fields — extra fields stored dynamically
await client.insert({
collection_name: 'flexible',
data: [
{ vector: [...], color: 'red', score: 0.95 },
{ vector: [...], color: 'blue', tags: ['a', 'b'] },
],
});
// Query dynamic fields
await client.query({
collection_name: 'flexible',
filter: 'color == "red"',
output_fields: ['color', 'score'],
});
await client.createCollection({
collection_name: 'docs',
fields: [
{
name: 'id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: true,
},
{ name: 'sparse_vector', data_type: DataType.SparseFloatVector },
],
});
await client.insert({
collection_name: 'docs',
data: [
{ sparse_vector: { 0: 0.5, 10: 0.3, 200: 0.8 } }, // dict format
{ sparse_vector: { 1: 0.1, 50: 0.9 } },
],
});
await client.search({
collection_name: 'docs',
data: [{ 0: 0.5, 10: 0.3 }],
anns_field: 'sparse_vector',
limit: 10,
});
await client.createCollection({
collection_name: 'multi_tenant',
fields: [
{
name: 'id',
data_type: DataType.Int64,
is_primary_key: true,
autoID: true,
},
{
name: 'tenant',
data_type: DataType.VarChar,
max_length: 64,
is_partition_key: true,
},
{ name: 'vector', data_type: DataType.FloatVector, dim: 128 },
],
num_partitions: 16,
});
// Milvus automatically routes by partition key
await client.search({
collection_name: 'multi_tenant',
data: [queryVector],
filter: 'tenant == "user_123"', // Scoped to partition
limit: 10,
});
For detailed guides on advanced features, visit the documentation:
TypeScript
99.9%