从 0 到实战:掌握向量数据库 Milvus,构建 AI 应用的核心能力

传统的数据库,比如 MySQL 等存的是精确值(数字、字符串),查询靠精确匹配或 LIKE 模糊搜索。

而传统数据库查询的精确匹配或 LIKE 模糊搜索没发进行语义搜索。此时向量数据库,比如 Milvus 就登场了。

向量数据库存的是向量 (一组浮点数数组,如 [0.12, -0.34, 0.56, ...]),查询靠语义相似度

比如你搜"猫",它能找回" kitten ""猫咪"甚至"宠物",因为它比较的是语义上的"距离",而非字面是否一致。

向量数据库应用场景

  • RAG 知识库:把文档向量化存到 Milvus,用户提问时搜出最相关片段喂给 LLM

  • 图片检索:以图搜图,根据视觉特征向量找相似图片

  • 推荐系统:用用户行为向量匹配相似用户或商品

  • 语义搜索:自然语言搜索非结构化文本

安装 Milvus

安装 Milvus 数据库需要借助 Docker 。使用 Docker 借助 Milvus 官方 github 仓库提供的 docker compose 配置文件可快速安装 Milvus :

github.com/milvus-io/m...

把这个配置文件下载下来,使用 docker compose 启动 Milvus :

shell 复制代码
docker compose -f ./milvus-standalone-docker-compose.yml up -d

用到的镜像根据配置文件自动下载,跑起来之可以在 docker 桌面端看到下载 milvusetcdminio 三个镜像:

跑起来的 milvus 容器:

Milvus 通过 19530 端口对外暴露服务。

通过下面命令验证服务是否正常:

bash 复制代码
docker ps --filter "name=milvus"
# 应看到三个容器均为 healthy

Milvus 数据库增删改查案例

接下来会使用 Node.js 语言实现 Milvus 数据库的增删改查案例。

Node.js 项目初始化

创建 milvus-test 文件夹,安装以下依赖包:

  • @zilliz/milvus2-sdk-node: Milvus 官方 Node.js SDK

  • @langchain/openai: 调用嵌入模型,将文本转为向量

  • dotenv: 加载 .env 中的环境变量

.env 中配置阿里云百炼的 API Key:

ini 复制代码
DASHSCOPE_API_KEY=sk-xxxxxxxx

在写代码之前,先理解 Milvus 向量数据库几个关键概念:

  • Collection:相当于关系数据库中的一张表,存同类型的数据。
  • Schema:定义字段结构,如主键 ID、标题、正文、向量。
  • Vector Field:存储向量数据的特殊字段,搜索时用它计算相似度。
  • Index:为向量字段建索引,否则只能暴力扫描,速度极慢。

项目结构

创建以下项目文件结构:

bash 复制代码
src/
├── config.js        # 统一配置:Milvus 地址、嵌入模型参数
├── client.js        # MilvusClient 单例
├── embedding.js     # 文本 → 向量(调用百炼 text-embedding-v4)
├── collection.js    # 集合管理:创建 Schema、建索引、加载到内存
├── create.js        # 增:插入数据
├── read.js          # 查:向量搜索 + 标量查询
├── update.js        # 改:Upsert(有则更新,无则插入)
├── delete.js        # 删:按 ID / 按条件删除
└── index.js         # 主入口,串联演示完整流程

连接 Milvus

js 复制代码
// src/client.js
import { MilvusClient } from "@zilliz/milvus2-sdk-node";

export const milvusClient = new MilvusClient({
  address: "localhost:19530", // Docker 暴露的 gRPC 端口
  database: "default",
  timeout: 30000,
});

socket 连接是惰性的,只有在发起第一次请求时才真正建立。

文本向量化(Embedding)

向量数据库本身不负责把文本变成向量,这一步需要嵌入模型 完成。这里用阿里云百炼的 text-embedding-v4,输出 1024 维向量。

js 复制代码
// src/embedding.js
import { OpenAIEmbeddings } from "@langchain/openai";

const embeddings = new OpenAIEmbeddings({
  openAIApiKey: process.env.DASHSCOPE_API_KEY,
  modelName: "text-embedding-v4",
  dimensions: 1024,
  configuration: {
    baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
  },
});

// 单条文本 → 向量
export async function embedText(text) {
  return embeddings.embedQuery(text);
}

// 批量文本 → 向量数组
export async function embedTexts(texts) {
  return embeddings.embedDocuments(texts);
}

embedQuery 接收单个字符串,将该字符串转为向量。

embedDocuments 接收字符串数组,将字符串数组转为向量数组。

创建 Collection

Collection 是数据的容器,需要先定义 Schema、建索引,最后加载到内存。

js 复制代码
// src/collection.js
import { DataType, MetricType, IndexType } from "@zilliz/milvus2-sdk-node";

await milvusClient.createCollection({
  collection_name: "demo_articles",
  fields: [
    {
      name: "id",
      data_type: DataType.VarChar,
      is_primary_key: true,
      type_params: { max_length: "64" },
    },
    {
      name: "title",
      data_type: DataType.VarChar,
      type_params: { max_length: "512" },
    },
    {
      name: "content",
      data_type: DataType.VarChar,
      type_params: { max_length: "65535" },
    },
    {
      name: "embedding",
      data_type: DataType.FloatVector,
      type_params: { dim: "1024" },
    },
  ],
  enable_dynamic_field: true, // 允许存入未在 Schema 中声明的字段
});

// 为向量字段建索引(搜索前必须)
await milvusClient.createIndex({
  collection_name: "demo_articles",
  field_name: "embedding",
  index_type: IndexType.IVF_FLAT, // 倒排索引,适合百万级数据
  metric_type: MetricType.COSINE, // 余弦相似度
  params: { nlist: 128 },
});

// 加载到内存(搜索前必须)
await milvusClient.loadCollectionSync({
  collection_name: "demo_articles",
});

三步走:建表 → 建索引 → 加载。缺一不可。

增(Insert)

插入数据前,先把文本转为向量,再连同原文一起写入。

js 复制代码
// src/create.js
const contents = articles.map((a) => a.content);
const embeddings = await embedTexts(contents); // 批量向量化

const rows = articles.map((article, i) => ({
  id: article.id,
  title: article.title,
  content: article.content,
  embedding: embeddings[i], // 向量字段
}));

const result = await milvusClient.insert({
  collection_name: "demo_articles",
  data: rows,
});

// 刷新使数据可被搜索
await milvusClient.flushSync({ collection_names: ["demo_articles"] });

关于 flush :Milvus 的数据先写内存再异步落盘。flushSync 会阻塞等待落盘完成,确保后续搜索能查到刚插入的数据。

查(Search / Query)

Milvus 提供两种"查":

向量相似度搜索(ANN Search)

把查询文本也转成向量,在向量空间找 Top-K 最近邻居。

js 复制代码
// src/read.js
const queryVector = await embedText("什么是向量数据库?");

const result = await milvusClient.search({
  collection_name: "demo_articles",
  data: queryVector, // 查询向量
  anns_field: "embedding", // 在哪个向量字段上搜索
  limit: 3, // Top-K
  output_fields: ["id", "title"], // 返回哪些标量字段
  params: { nprobe: 16 }, // 搜索精度(越大越准但也越慢)
});

运行结果示例:

less 复制代码
搜索查询: "什么是向量数据库?"
  #1 [article-002] 向量数据库入门:从零开始学习 Milvus (相似度: 0.8252)
  #2 [article-004] Docker 容器化部署最佳实践 (相似度: 0.3095)

标量查询(按 ID 或条件过滤)

不走向量搜索,像传统数据库一样精确查询。

js 复制代码
// 按 ID 查询
await milvusClient.query({
  collection_name: "demo_articles",
  ids: ["article-001", "article-003"],
  output_fields: ["id", "title"],
});

// 按条件过滤
await milvusClient.query({
  collection_name: "demo_articles",
  filter: 'id like "article-%"',
  limit: 10,
});

改(Upsert)

Milvus 的更新操作是 Upsert:主键已存在则覆盖(含向量重新计算),不存在则插入。

js 复制代码
// src/update.js
const vec = await embedText(newContent);

await milvusClient.upsert({
  collection_name: "demo_articles",
  data: [
    {
      id: "article-002", // 相同 ID → 覆盖旧数据
      title: "新标题",
      content: newContent,
      embedding: vec,
    },
  ],
});

await milvusClient.flushSync({ collection_names: ["demo_articles"] });

删(Delete)

支持按 ID 列表或按表达式删除。

js 复制代码
// src/delete.js

// 按 ID 删除
await milvusClient.delete({
  collection_name: "demo_articles",
  ids: ["article-005"],
});

// 按表达式删除
await milvusClient.delete({
  collection_name: "demo_articles",
  filter: 'id == "article-004"', // 对标量字段的条件表达式
});

// 每次删除后刷新
await milvusClient.flushSync({ collection_names: ["demo_articles"] });

效果演示

在 package.json 中添加 npm scripts 命令:

json 复制代码
{
  "scripts": {
    "start": "node src/index.js"
  }
}

运行 pnpm start 命令程序会依次执行:创建集合 → 插入 5 篇文章 → 语义搜索验证 → 按 ID 查询 → Upsert 更新 → 按 ID 删除 → 按条件删除。每一步都有清晰的日志输出。

受限于篇幅,这个只截取部分执行效果:

代码已上传 github 仓库:github.com/Panda-plus5...

安装 Milvus 可视化管理工具

Milvus 可视化管理工具推荐使用 Attu ,相当于 MySQL 的 Navicat 。

使用可视化管理工具可以方便查看数据库中的数据。

可以在以下链接获取安装包:

github.com/zilliztech/...

下载后直接安装,使用默认配置连接:

连接后可以方便地查看 Entity 数据:

总结

在 AI 时代,语义搜索已成为 RAG、智能问答等应用的核心能力,而传统数据库(如 MySQL)受限于精确匹配和模糊查询,无法理解"猫"与" kitten "之间的语义关联。向量数据库(如 Milvus)正是填补这一空白------它将文本、图片等非结构化数据映射为高维向量,通过相似度计算实现"理解含义"的搜索。

掌握了上文的增删改查,你就能将 Milvus 融入实际项目。

欢迎读者点赞、收藏!

相关推荐
猎头南楼3 分钟前
具身智能模型部署方向的能力要求与技术栈梳理
人工智能·深度学习·算法
风吹心凉3 分钟前
Agent大脑-skills技能包
人工智能
benchmark_cc6 分钟前
Python量化实战:如何检测并剔除历史数据中的“闪崩/乌龙指”异常价格点?
开发语言·人工智能·python·量化·quantdash·量化数据源
ChaITSimpleLove8 分钟前
.NET 10 的 AI 技术栈全景:M.E.AI、MCP 与 Agent Framework 深度解析
人工智能·.net·ai agent·mcp·agent framework·m.e.ai·hosted agents
测绘第一深情10 分钟前
深度学习中如何通过阈值搜索平衡 Precision 和 Recall
人工智能·深度学习
Highcharts.js23 分钟前
Highcharts 下钻(Drilldown)柱状图 Demo
数据库·信息可视化·hbase·highcharts·drilldown·js模块·下钻图表
哈哈哈也不行吗34 分钟前
用大角几何整理几何教研案例:从作图到复用的一个思路
人工智能·在线工具·几何绘图·大角几何
新知图书36 分钟前
16.1 基于MCP的多Agent旅行规划助手系统概述
人工智能·agent·ai agent·智能体
翼龙云_cloud37 分钟前
阿里云国际渠道代理商:如何在ECS上部署Flask应用?
运维·数据库·阿里云·flask·云计算