Node.js 操作 Milvus 完整实战案例
本文整理开箱即用 的 Node.js 操作 Milvus 2.x 完整案例,覆盖连接服务、创建集合、插入向量、创建索引、向量搜索、删除集合 等核心流程,基于 Milvus 官方 Node.js SDK @zilliz/milvus2-sdk-node 实现。
一、环境准备
1. 启动 Milvus 服务
推荐用 Docker 快速启动 Milvus 2.x(最简单机版):
bash
# 下载 Milvus Docker 编排文件
wget https://github.com/milvus-io/milvus/releases/download/v2.4.4/milvus-standalone-docker-compose.yml -O docker-compose.yml
# 启动服务
docker-compose up -d
# 验证服务(默认端口:19530)
docker ps | grep milvus
Milvus 默认地址:
localhost:19530,管理工具:Attu(可选,可视化操作)
2. 初始化 Node.js 项目
bash
# 创建项目文件夹
mkdir milvus-node-demo && cd milvus-node-demo
# 初始化项目
npm init -y
# 安装核心依赖
npm install @zilliz/milvus2-sdk-node dotenv
@zilliz/milvus2-sdk-node:Milvus 官方 Node.js SDKdotenv:管理环境配置(Milvus 地址、端口等)
二、完整可运行代码
创建 index.js 文件,直接复制运行,所有核心操作已封装:
javascript
// 导入依赖
require('dotenv').config();
const { MilvusClient, DataType } = require('@zilliz/milvus2-sdk-node');
// ===================== 1. 配置信息 =====================
const MILVUS_CONFIG = {
address: process.env.MILVUS_ADDRESS || 'localhost:19530', // Milvus 地址
username: process.env.MILVUS_USER || '', // 用户名(可选)
password: process.env.MILVUS_PASSWORD || '', // 密码(可选)
};
// 集合名称(自定义)
const COLLECTION_NAME = 'node_milvus_demo';
// 向量维度(自定义,需和插入数据匹配)
const VECTOR_DIM = 128;
// ===================== 2. 初始化 Milvus 客户端 =====================
const client = new MilvusClient(MILVUS_CONFIG);
// ===================== 3. 核心操作函数 =====================
/**
* 1. 连接 Milvus 服务
*/
async function connectMilvus() {
const res = await client.connect();
console.log('✅ Milvus 连接成功:', res);
}
/**
* 2. 创建集合(必须定义:主键、标量字段、向量字段)
*/
async function createCollection() {
// 定义集合字段结构
const collectionParams = {
collection_name: COLLECTION_NAME,
fields: [
// 主键字段(必选,int64/varChar,唯一标识)
{
name: 'id',
dtype: DataType.Int64,
is_primary_key: true,
auto_id: false, // 手动设置ID,true为自动生成
},
// 标量字段(存储文本/普通数据,用于过滤)
{
name: 'title',
dtype: DataType.VarChar,
max_length: 255,
},
// 向量字段(必选,存储特征向量)
{
name: 'vector',
dtype: DataType.FloatVector,
dim: VECTOR_DIM, // 向量维度
},
],
};
// 先检查集合是否存在,存在则删除
const hasCollection = await client.hasCollection({ collection_name: COLLECTION_NAME });
if (hasCollection) {
await client.dropCollection({ collection_name: COLLECTION_NAME });
console.log('🗑️ 旧集合已删除');
}
// 创建新集合
const res = await client.createCollection(collectionParams);
console.log('✅ 集合创建成功:', res);
}
/**
* 3. 插入向量数据(生成测试数据)
*/
async function insertData() {
// 生成 10 条测试数据
const data = [];
for (let i = 1; i <= 10; i++) {
data.push({
id: i,
title: `测试数据_${i}`,
// 生成 128 维随机向量(值范围:-1 ~ 1)
vector: Array.from({ length: VECTOR_DIM }, () => Math.random() * 2 - 1),
});
}
// 插入数据
const res = await client.insert({
collection_name: COLLECTION_NAME,
data: data,
});
console.log('✅ 数据插入成功,插入条数:', res.insert_cnt);
}
/**
* 4. 创建向量索引(必选!无索引无法高效搜索)
*/
async function createIndex() {
const indexParams = {
collection_name: COLLECTION_NAME,
field_name: 'vector', // 要创建索引的向量字段
index_type: 'FLAT', // 索引类型:FLAT(小数据量,精准搜索)
metric_type: 'L2', // 相似度计算方式:L2(欧氏距离)/IP(内积)/COSINE(余弦)
};
const res = await client.createIndex(indexParams);
console.log('✅ 索引创建成功:', res);
}
/**
* 5. 加载集合到内存(必选!加载后才能搜索)
*/
async function loadCollection() {
const res = await client.loadCollection({ collection_name: COLLECTION_NAME });
console.log('✅ 集合加载成功:', res);
}
/**
* 6. 向量相似度搜索(核心功能)
*/
async function searchVector() {
// 生成 1 条查询向量(和插入数据维度一致)
const queryVector = Array.from({ length: VECTOR_DIM }, () => Math.random() * 2 - 1);
// 搜索参数
const searchParams = {
collection_name: COLLECTION_NAME,
data: [queryVector], // 查询向量
anns_field: 'vector', // 搜索的向量字段
topk: 3, // 返回最相似的前3条结果
metric_type: 'L2', // 相似度计算方式
output_fields: ['id', 'title'], // 返回的标量字段
};
const res = await client.search(searchParams);
console.log('🔍 向量搜索结果:', JSON.stringify(res.results, null, 2));
}
/**
* 7. 释放集合 + 删除集合(清理资源)
*/
async function cleanResource() {
// 释放集合(从内存卸载)
await client.releaseCollection({ collection_name: COLLECTION_NAME });
// 删除集合
await client.dropCollection({ collection_name: COLLECTION_NAME });
console.log('🗑️ 资源清理完成');
}
// ===================== 4. 执行主流程 =====================
async function main() {
try {
await connectMilvus();
await createCollection();
await insertData();
await createIndex();
await loadCollection();
await searchVector();
await cleanResource();
} catch (error) {
console.error('❌ 操作失败:', error);
}
}
// 启动程序
main();
三、核心模块解析
1. 数据类型定义
DataType.Int64:主键数字类型DataType.VarChar:文本标量类型DataType.FloatVector:浮点型向量(最常用)
2. 关键必选步骤
- 创建集合 :必须定义主键 +向量字段
- 创建索引:Milvus 无索引无法执行搜索
- 加载集合:集合必须加载到内存才能读写
- 向量维度匹配:插入向量、查询向量、集合定义的维度必须一致
3. 索引类型说明
FLAT:小数据量(万级内),精准搜索,无需调参(新手首选)IVF_FLAT:大数据量(百万级),分桶搜索,速度更快COSINE/L2/IP:三种相似度计算方式(文本/图像推荐 COSINE)
四、运行测试
- 确保 Milvus 服务已启动
- 执行代码:
bash
node index.js
-
控制台输出:
✅ Milvus 连接成功
🗑️ 旧集合已删除
✅ 集合创建成功
✅ 数据插入成功,插入条数: 10
✅ 索引创建成功
✅ 集合加载成功
🔍 向量搜索结果: [
{ id: 5, score: 12.345, title: '测试数据_5' },
{ id: 2, score: 15.678, title: '测试数据_2' },
{ id: 8, score: 18.901, title: '测试数据_8' }
]
🗑️ 资源清理完成
五、常用扩展操作
1. 根据主键查询数据
javascript
async function queryById() {
const res = await client.query({
collection_name: COLLECTION_NAME,
filter: 'id in [1,2,3]', // 过滤条件
output_fields: ['id', 'title'],
});
console.log('📋 查询结果:', res);
}
2. 删除数据
javascript
async function deleteData() {
const res = await client.delete({
collection_name: COLLECTION_NAME,
filter: 'id = 5', // 删除id=5的数据
});
console.log('🗑️ 删除成功:', res);
}
3. 查看集合信息
javascript
async function getCollectionInfo() {
const res = await client.describeCollection({ collection_name: COLLECTION_NAME });
console.log('📊 集合信息:', res);
}
六、常见问题排查
- 连接失败:检查 Milvus 地址/端口(默认19530),确认 Docker 服务正常
- 搜索失败:未创建索引 / 未加载集合 / 向量维度不匹配
- 插入失败:主键重复 / 字段类型不匹配 / 向量维度错误
总结
- 本案例覆盖 Milvus 全生命周期操作,代码可直接复制运行
- 核心流程:连接→建库→插数据→建索引→加载→搜索→清理
- 新手推荐用
FLAT索引,小数据量无学习成本 - 向量维度、索引类型、相似度算法是 Milvus 性能优化的核心