跳至主要内容

如何在 MongoDB 中存储与查询嵌入向量

了解如何使用 Atlas Vector Search 在 MongoDB 中存储、索引和查询嵌入向量。
· 8分钟 阅读

使用 AI 探索

LLM 和语义搜索的兴起从根本上改变了我们构建搜索、推荐和检索系统的方式。传统的关键词搜索—无论是通过 SQL LIKE、Lucene 倒排索引,还是全文索引—在用户期望自然语言理解的今天,正日益显得力不从心。

这正是嵌入向量(embeddings)和向量数据库发挥作用的地方。

MongoDB 在该领域通过Atlas Vector Search 快速演进,为开发者提供一个同时容纳文档 + 元数据 + 向量的单一数据库—统一于一个 API 之下。本文将带您了解:

  • 什么是 MongoDB。
  • 什么是查询嵌入向量,以及它们为何重要。
  • 何时应使用嵌入向量。
  • 如何在 MongoDB 中存储嵌入向量。
  • 如何使用 Python 生成与查询它们。

本教程可直接上手并集成到您的检索增强生成(RAG)、相似度搜索或推荐流程中。

什么是 MongoDB?

MongoDB 是面向文档的 NoSQL 数据库,以灵活的BSON 文档存储数据—BSON 是二进制编码的 JavaScript 对象表示(JSON)—一种在基于 Web 的应用间广泛用于传输与存储数据的文本对象表示。与刚性的关系型数据库不同,MongoDB 使模式演进更为简单,并提供:

  • 水平扩展(分片)。
  • 丰富的聚合框架。
  • 全文搜索。
  • 向量搜索。
  • 时序集合。
  • 模式灵活性。

MongoDB Atlas(全托管云服务)在此基础上进一步提供:

  • Atlas Search(基于 Lucene)。
  • Atlas Vector Search(通过 HNSW 索引实现语义搜索)。
  • 自动伸缩、备份、安全与监控。

MongoDB 已成为 AI 工作负载的有力选择,因为向量常与元数据并存,而 MongoDB Atlas 将这一切都整合进了一个系统。

什么是嵌入向量,我们为何使用查询嵌入向量?

在构建 AI 应用中的搜索或检索功能时,您首先会接触到嵌入向量这一概念。

嵌入向量本质上是一种数值表示,即一长列浮点数,用于捕捉一段文本(或图像、音频等)的含义。与其逐字对比,嵌入向量将文本映射到一个向量空间,使相似的想法彼此靠近。例如,考虑三条不同的用户表述:

  • 账单问题
  • 支付错误
  • 工资未到账

尽管措辞不同,这三者都描述了财务问题。优秀的嵌入模型会将这些文本在向量空间中置于彼此邻近的位置,使您可以基于含义而非关键词来检索。

当用户执行搜索时,这一点尤为重要。他们输入的文本——“我的工资为什么延迟了?”——也会被转换为一个嵌入向量。这个新向量称为查询嵌入向量。随后,您将该查询向量与所有已存储的嵌入向量进行比较,以找到语义上相似的文档。向量越接近,结果越相关。

借助Atlas Vector Search,MongoDB Atlas 让整个流程变得非常简单。将文档及其嵌入向量存入 MongoDB 集合后,Atlas 会创建一个向量索引(底层使用 HNSW),可以在大规模数据中快速检索相似文档。比如,若您存储了支持文章及其嵌入向量,一条查询如…

query = "Why isn't my salary showing up this month?"
query_vec = get_embedding(query) # Explained in below examples

…即可直接在 MongoDB 中使用:

results = collection.aggregate([
    {
        "$vectorSearch": {
            "path": "embedding",
            "queryVector": query_vec,
            "index": "vector_index",
            "limit": 3
        }
    }
])

MongoDB 将自动返回与查询最接近的 3 篇支持文章—无需进行任何关键词匹配或手动打分。

这就是在 MongoDB Atlas 中使用嵌入向量的威力:您存储的是“含义”而不仅是文本,您基于“意图”而不仅是词语进行查询。这种转变也是嵌入向量成为语义搜索、RAG 系统、AI 助手和智能知识库核心构件的原因。

何时使用查询嵌入向量

当您需要语义相似性时使用嵌入向量,例如:

检索增强生成(RAG)

  • 为您的 LLM 提供来自知识库的准确上下文
  • 替代脆弱的关键词搜索

需要深度理解的聊天机器人

  • 门户服务台
  • 客户支持

产品推荐

  • “与该商品相似的商品”

文档或重复检测

  • 聚类
  • 主题归类

当关键词搜索失效时

  • 如“工资入账延迟” vs. “支付处理问题”之类的查询

不要在以下情况下使用嵌入向量:

  • 您需要精确匹配(ID、发票号)。
  • 您的数据集很小(简单搜索即可)。
  • 您需要数值过滤/比较(应由元数据处理)。

如何在 MongoDB 中存储嵌入向量

MongoDB 的妙处在于嵌入向量天然适合放在文档中。您只需将其存为浮点数组即可。

示例文档模式

以下是一个典型文档结构:

{
  "_id": "uuid-123",
  "text": "This is a sample document about MongoDB vector search.",
  "embedding": [0.123, -0.241, 0.998, ...],
  "tags": ["mongodb", "vector", "ai"],
  "createdAt": "2025-01-01T10:20:00Z"
}

需牢记的重要事项:

  • 同一集合中的每个嵌入向量必须具有相同的维度。
  • 嵌入向量理想情况下应存为float32(MongoDB 内部会转换为 float64)。
  • 如果文档很长,建议在嵌入前先切分为片段。
  • 将元数据单独存储—如标签、类别、URL、时间戳等。这能让混合搜索更强大。

在 MongoDB 中创建向量索引(关键步骤)

在存储或查询嵌入向量之前,必须在 MongoDB Atlas 中创建一个向量搜索索引。

在 MongoDB Atlas 中,前往: Atlas → Database → Collections → Search → Create Search Index

使用如下定义:

{
  "fields": [
    {
      "type": "vector",
      "path": "embedding",
      "numDimensions": 1536,
      "similarity": "cosine"
    }
  ]
}

这告诉 MongoDB:

  • 字段 embedding 包含向量。
  • 每个向量有 1536 个维度。
  • 使用余弦相似度进行排序。

该索引为所有向量搜索查询提供支持。

MongoDB 内置向量搜索功能,支持:

  • 余弦相似度。
  • 欧氏距离。
  • 点积(dotProduct)打分。

可根据您的嵌入模型选择—但我们该如何判断?下面深入解析。

余弦相似度

衡量内容

对齐程度——即两个向量之间的夹角。它忽略幅度,仅关注方向。

直觉理解

  • 若两个向量方向相同 → 相似度接近1
  • 方向相反 → –1
  • 正交(无关) → 0

适用场景

当幅度不重要,只关注所表达的模式或概念时,使用余弦相似度。

常见用法

  • 文本嵌入/NLP
  • 语义搜索
  • 基于“含义”而非“规模”的推荐系统

对于大多数嵌入模型,余弦相似度是最稳妥的默认选择。

欧氏距离

衡量内容

衡量空间中两个向量之间的直线距离。

直觉理解

  • 距离小 → 向量相似
  • 距离大 → 向量相距远

适用场景

当绝对值与幅度很重要,而不仅是方向时,使用欧氏距离。

常见用法

  • 图像嵌入
  • 物理测量/传感器数据
  • 如 K-means 等聚类算法(内部使用欧氏距离)

如果您的数据天然存在于一个几何空间(如像素强度),欧氏距离往往更合理。

点积

衡量内容

它同时衡量相似性与幅度。

数学形式:dot(u, v) = |u| × |v| × cos(θ)

直觉理解

  • 幅度更大且方向更对齐 → 分数更高
  • 对向量长度敏感
  • 不自动归一化

适用场景

当您希望更长的向量产生更大影响,或当嵌入模型以点积为训练假设时,使用点积。

常见用法

  • 假设使用内积打分的大语言模型嵌入向量
  • 神经网络中的相似度层
  • “强度”有意义的推荐模型

快速经验法则

度量

适合场景

避免情形

Cosine

文本、语义搜索、通用嵌入

幅度重要

Euclidean

图像、几何特征、聚类

数据缩放任意

Dot product

以内积训练的模型、推荐系统

幅度会扭曲相似性

在 MongoDB 中生成、存储并查询嵌入向量(Python 教程)

让我们以构建真实系统的方式逐步演示。

安装依赖

pip install pymongo openai

生成嵌入向量

使用 OpenAI(可替换为您偏好的任意嵌入模型提供商):

import os
from openai import OpenAI

os.environ["OPENAI_API_KEY"] = "your_api_key_here"
client = OpenAI()

def get_embedding(text: str):
    response = client.embeddings.create(
        model="text-embedding-3-small",
        input=text
    )
    return response.data[0].embedding

连接 MongoDB 并插入文档

使用 OpenAI(可替换为您偏好的任意嵌入模型提供商):

from pymongo import MongoClient
import uuid

mongo = MongoClient("<MONGODB_ATLAS_URI>")
db = mongo["vector_db"]
collection = db["documents"]

text = "This is a sample document about MongoDB vector search."
embedding = get_embedding(text)

document = {
    "_id": str(uuid.uuid4()),
    "text": text,
    "embedding": embedding,
    "tags": ["mongodb", "search"],
}

collection.insert_one(document)
print("Document inserted successfully!")

至此,您的数据已准备好进行语义搜索。

在 MongoDB 中查询嵌入向量

接下来是有趣的部分:使用向量查询检索相似文档。MongoDB 在聚合管道中使用$vectorSearch。

生成查询向量

from pymongo import MongoClient
query = "How does MongoDB handle semantic search?"
query_vec = get_embedding(query)

执行向量搜索(查询嵌入向量)

results = collection.aggregate([
    {
        "$vectorSearch": {
            "index": "vector_index",
            "path": "embedding",
            "queryVector": query_vec,
            "numCandidates": 100,
            "limit": 5,
            "similarity": "cosine"
        }
    },
    {
        "$project": {
            "text": 1,
            "score": {"$meta": "vectorSearchScore"}
        }
    }
])

for r in results:
    print(r)

这将返回五个语义上最相似的文档。

这对需要语义搜索的 RAG 流水线非常有用。

上述查询的逐步说明

$vectorSearch → 查找其embedding 字段最接近 queryVector 的文档,使用指定的相似度度量

numCandidates → 引擎在选出最终结果前应考虑的候选数量

limit → 要返回的最终相似结果数量

$project → 返回原始文本以及名为 score 的特殊字段

score 字段是什么?

MongoDB Atlas Vector Search 返回一个特殊的元数据字段, "score": {"$meta": "vectorSearchScore"},用于指示存储向量与查询向量的相似程度。

该分数的含义取决于您选择的相似度度量,如下所述:

相似度度量

分数含义

分数越高=越相似?

分数范围

cosine

向量间的角度相似性

是

–1 到 +1

euclidean

负的 L2 距离

否——越接近 0 越相似

–∞ 到 0

dotProduct

向量幅度的对齐程度

是

–∞ 到 +∞

最佳实践

  • 将长文档切分(每段 300–500 个 token): 提升相关性,避免对长文本整体嵌入
  • 单独存储元数据: 便于过滤与排序
  • 批量生成嵌入: 提升吞吐并降低模型成本
  • 在模型端使用 float32 嵌入: MongoDB 内部使用 float64,但接受 float32 数组
  • 仅为向量字段创建索引: 将其他字段加入索引会增加内存与时延

常见陷阱与规避

问题

成因

维度不匹配

查询向量维度 ≠ 索引维度

结果不相关

存储与查询使用了不同模型

搜索缓慢

numCandidates 过多或集群规格不足

文档过大

16MB 文档大小上限

相似度度量选择错误

模型以余弦训练却使用点积

结语

嵌入向量与语义搜索已成为现代 AI 产品的基石。无论您在构建聊天机器人、RAG 流水线、推荐引擎还是智能搜索层,都需要一种可靠的方式来存储向量并高效查询。

MongoDB 为您提供统一的平台:

  • 文本在此存放。
  • 元数据在此存放。
  • 嵌入向量在此存放。
  • 向量搜索在此运行。
  • 一切共同扩展。

这避免了同时管理多个数据库的复杂性,让您专注于构建产品能力,而非基础设施。

FAQs

如果在 MongoDB 中使用嵌入向量,我还需要单独的向量数据库吗?

不需要。MongoDB Atlas Vector Search 是内置的,您可以在同一处存储文档、元数据与向量,无需使用 Pinecone 或 Milvus 等独立的向量数据库。

在 MongoDB 中应使用何种嵌入向量维度?

使用您的嵌入模型所提供的维度(如 768 或 1536)。集合中的所有文档必须使用与向量索引相同的维度。

MongoDB 能进行混合搜索(元数据 + 向量搜索)吗?

您可以先使用 $match 进行过滤,然后在同一聚合管道中应用 $vectorSearch——非常适合 RAG 与推荐系统。

MongoDB 适合大规模向量搜索工作负载吗?

可以。MongoDB 在 Atlas Search 中使用基于 HNSW 的索引,能够很好地扩展至数百万文档。吞吐量取决于索引大小、集群规格与负载模式。

我可以在 MongoDB 中使用任意嵌入模型吗?

当然。MongoDB 与模型无关。您可以使用 OpenAI、HuggingFace、Cohere、本地模型或自定义嵌入——只要维度与索引匹配即可。

Nilesh Soni

作者

Nilesh Soni

Uber 资深软件工程师

主题