从 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 融入实际项目。

欢迎读者点赞、收藏!

相关推荐
tachibana21 小时前
知识库文档上传接口
数据库·人工智能·大模型·llm
手写码匠1 小时前
华为云Flexus+DeepSeek征文|Agent 记忆系统实战:用 DeepSeek-R1/V3 + Dify 会话变量打造跨会话长期记忆
人工智能·深度学习·算法·aigc
可乐ea1 小时前
Tool Calling 工具调用:让 Agent 查询数据库、调用接口和执行任务
数据库·prompt·agent·tool
武子康1 小时前
Pi Agent Loop 源码解析:Context、Streaming、Tool Calling、Steering 与停止条件
人工智能·llm·agent
小当家.1051 小时前
MCP 协议深度解析:AI 领域的 USB-C 接口
开发语言·人工智能·agent·tool·mcp
动物园猫1 小时前
无人机灾害场景人体目标检测数据集:10,000张图像 | 目标检测
人工智能·目标检测·无人机
神奇霸王龙1 小时前
AgentDesk 配置 Codex+ selltoken 中转 API 实测教程(2026 年 8 月更新)
人工智能·ai·ai编程·策略模式·codex·agentdesk
3A Cloud1 小时前
Architecture Diagram Skill 详细介绍
人工智能·笔记·信息可视化
123_不打狼1 小时前
AI Agent可观测性:破解多步推理黑盒的技术实践
大数据·人工智能