You need to enable JavaScript to run this app.
文档中心
文档数据库 MongoDB 版

文档数据库 MongoDB 版

复制全文
下载 pdf
常见问题
向量搜索
复制全文
下载 pdf
向量搜索
本文汇总了 MongoDB 8.3 版本向量搜索的常见问题。
说明
  • 当前 MongoDB 8.3 版本正在灰度发布中,如需使用向量搜索功能,请提交工单联系技术申请使用。
  • MongoDB 8.3 版本的向量搜索功能通过集成的 mongot 搜索节点提供。mongot 是专为全文搜索和向量搜索设计的索引与查询执行引擎,负责管理 Search 索引并执行检索查询。
如何选择相似度计算方式?
在创建 Search 索引时,需要通过 similarity 参数指定相似度计算方法。MongoDB 向量搜索支持三种算法。
核心选择原则
根据向量数据的归一化状态和业务场景决策,具体如下:
  • cosine(余弦相似度)
  • 最常用,适用于文本嵌入和语义检索场景。它衡量两个向量在方向上的相似程度,对向量的模长不敏感,是处理由各类 Embedding 模型(如 text-embedding-v4)生成向量的通用选择。如果无法确定向量的归一化状态,选择 cosine 是安全的默认选项。
  • dotProduct(点积)
  • 当且仅当向量已归一化(即模长为 1)时,点积与余弦相似度等价,且计算效率更高。若您的向量来自归一化模型,或您已手动归一化,可优先选用此方法以提升性能。
  • euclidean(欧氏距离)
  • 衡量向量在空间中的绝对距离,距离越小越相似。适用于特征向量空间中的绝对距离度量场景,如图像特征比对或物理特征相近性判断。
配置示例
fields: [{
"type": "vector",
"path": "embedding",
"numDimensions": 1536,
"similarity": "cosine" // 替换为 dotProduct 或 euclidean
}]
如何选择量化/压缩方式?
量化技术通过压缩向量数据的精度,显著降低存储和内存开销,是降低大规模向量搜索成本的关键手段。您可以在索引定义中通过 quantization 参数指定量化策略。
  • none(不量化)
  • 保精度最高,成本也最高。存储和检索使用原始 32 位浮点向量。适用于向量数量较小或对检索精度有极致要求的场景。
  • scalar(标量量化)
  • 平衡之选。将 32 位浮点数映射为更小的整数(如 int8),可将内存和存储开销降低约 75%(降至原来的 1/4),同时保持良好的检索精度,通常能保留 90% 以上的召回率。是大多数生产环境推荐的默认选项。
  • binary(二值量化)
  • 极致压缩。将每个维度压缩为 1 位(0 或 1),内存开销可降低约 96%(降至原来的 1/24)。为了弥补精度损失,MongoDB 会自动执行重打分(Rescoring)步骤,即使用原始全精度向量对二进制检索的 top-K 结果进行重新排序,以尽可能保证最终结果的准确性。适用于百万级、十亿级规模的向量场景,且对成本极度敏感、可接受微小精度损失的业务。
配置示例
fields: [{
"type": "vector",
"path": "embedding",
"numDimensions": 1536,
"similarity": "cosine",
"quantization": "scalar" // 或 binary
}]
如何使用多个向量字段?
您可以在同一个集合中存储多个向量字段。例如,为商品标题生成一个向量,为商品描述生成另一个向量,为商品图片再生成一个向量。这些字段都可以在同一个 Search 索引中定义。
注意
目前 $vectorSearch 阶段一次只能对一个向量字段进行检索。也就是说,您无法在一次查询中直接对"标题向量"和"描述向量"同时进行搜索并自动合并结果。
推荐方案:分别查询,再合并结果
您可以对每个向量字段分别执行 $vectorSearch,然后使用聚合管道将结果合并。
方法一:使用 $unionWith 合并
// 先对 title_embedding 进行向量检索
const pipelineA = [
{ $vectorSearch: { path: "title_embedding", queryVector: [...], numCandidates: 100, limit: 20 } },
{ $project: { _id: 1, title: 1, score: { $meta: "vectorSearchScore" }, source: { $literal: "title"
} } }
];
// 再对 desc_embedding 进行向量检索
const pipelineB = [
{ $vectorSearch: { path: "desc_embedding", queryVector: [...], numCandidates: 100, limit: 20 } },
{ $project: { _id: 1, title: 1, score: { $meta: "vectorSearchScore" }, source: { $literal: "desc"
} } }
];
// 使用 $unionWith 合并两个结果,在应用层或后续聚合阶段按权重重新打分排序
db.products.aggregate([
{ $unionWith: { coll: "products", pipeline: pipelineA } },
{ $unionWith: { coll: "products", pipeline: pipelineB } },
// 按 _id 分组,合并分数并排序
{ $group: { _id: "$_id", title: { $first: "$title" }, scores: { $push: "$score" } } },
{ $addFields: { finalScore: { $sum: "$scores" } } },
{ $sort: { finalScore: -1 } },
{ $limit: 10 }
]);
说明
$unionWith 是 MongoDB 通用的聚合管道操作符,适用于所有版本。上述示例中,我们分别对两个向量字段执行检索,然后通过 $unionWith 合并结果,再按 _id 分组后对分数求和排序。您也可以根据业务需要,为不同字段分配不同的权重。
方法二:使用 $rankFusion
如果您的 MongoDB 版本是 8.3 或更高,可以使用 $rankFusion 阶段来更简洁地合并结果。$rankFusion 会自动对多个 $vectorSearch 的结果进行去重和融合排序。
db.products.aggregate([
{
$rankFusion: {
input: {
pipelines: {
// 在标题向量中检索
titleSearch: [
{ $vectorSearch: {
index: "vector_index",
path: "title_embedding",
queryVector: [0.1, 0.2, ...],
numCandidates: 100,
limit: 20
}}
],
// 在描述向量中检索
descSearch: [
{ $vectorSearch: {
index: "vector_index",
path: "desc_embedding",
queryVector: [0.1, 0.2, ...],
numCandidates: 100,
limit: 20
}}
]
}
},
// 可选:为不同管道分配权重
combination: {
weights: { titleSearch: 0.6, descSearch: 0.4 }
}
}
},
{ $limit: 10 }
]);
何时需要添加过滤字段?
当您需要在向量搜索的基础上,叠加精确的条件筛选(如"查询与某商品描述相似,且价格低于 500 元、库存充足的商品")时,就需要添加过滤字段。
操作方式
  1. 索引定义:在 Search 索引的 fields 中,为需要过滤的字段(如 price, category, inStock)指定 type: "filter"
  1. 查询阶段:在 $vectorSearch 阶段使用 filter 参数传入 MQL 过滤条件。
索引定义示例
{
fields: [
{ type: "vector", path: "embedding", ... },
{ path: "category", type: "filter" },
{ path: "price", type: "filter" }
]
}
查询示例
db.collection.aggregate([
{
$vectorSearch: {
index: "vector_index",
path: "embedding",
queryVector: [...],
filter: { $and: [ { category: "Electronics" }, { price: { $lt: 500 } } ] },
numCandidates: 100,
limit: 10
}
}
]);
注意
  • 您必须在索引中将过滤字段定义为 filter 类型,否则过滤操作无法生效。
  • 筛选后的查询通常比未筛选的查询慢,因为需要先执行预过滤再计算向量相似度。过滤性能取决于过滤条件的选择性——选择性越高(匹配的文档越少),性能通常越好。
  • 对数据进行预过滤不会影响 $vectorSearch 返回的相似度分数(范围 0~1)。
  • 启用量化(scalarbinary)可以解决预过滤查询的内存问题,而无需增加更多内存。
建议将选择性高(即不同值较多的字段,如 userId)作为过滤字段,以有效缩小检索范围,提升性能。
如何估算 mongot 的内存与存储?
向量搜索依赖独立于 mongod 的搜索进程 mongot,您需要为 mongot 合理规划存储与内存资源。估算的核心思路是先统计 mongod 中的向量数据总量,再推算出 mongot 索引所需的存储和内存。最终规格建议预留 40% 剩余空间。
不同实例类型的估算方式有所不同,具体如下。
实例类型
估算方式
副本集实例
固定 2 个 mongot 节点,各持有完整索引。
分片集群实例
每个分片部署 2 个 mongot 节点,各索引本分片数据。可按全量资源 ÷ 分片数近似估算单分片所需资源(实际因数据分布可能略有偏差,建议适当预留余量)。
您可根据以下步骤完成 mongot 内存与存储的估算。
  1. 查询 mongod 中的向量数据大小
  • 方法 A:通过公式计算(推荐)
  • 如果已知向量维度和文档数量,可使用以下公式。
  • 向量数据总大小(GiB)= 文档数量 × 向量维度 × 4 ÷ 1024³
说明
  • 4 表示 float32(32 位单精度浮点数)类型每个维度占 4 字节。
  • 1024³ 用于将字节转换为 GiB(1 GiB = 1024³ 字节)。
  • 向量维度由您使用的 embedding 模型决定。embedding 模型是将文本转换为向量的 AI 模型,由 OpenAI、Google、Cohere 等厂商提供,也可从 Hugging Face 等开源社区获取。常见模型的维度参考:OpenAI ada-002(1536)、OpenAI 3-large(3072)、Cohere v3(1024)、Google gecko(768)。MongoDB 支持的维度上限为 8192,详情请参见 $vectorSearch(聚合阶段)
  • 计算示例
  • 场景
    文档数量
    常用模型
    维度
    计算过程
    结果
    小型知识库
    10 万
    Google gecko
    768
    100000 × 768 × 4 ÷ 1024³
    0.28 GiB
    中型商品库
    100 万
    OpenAI ada-002
    1536
    1000000 × 1536 × 4 ÷ 1024³
    5.72 GiB
    大型语料库
    1000 万
    OpenAI ada-002
    1536
    10000000 × 1536 × 4 ÷ 1024³
    57.2 GiB
  • 单条向量大小示例:1536 维 × 4 = 6144 字节 ≈ 6 KiB。
  • 方法 B:通过 MongoDB Shell 查询
  • 如果您不确定向量维度,或集合中存在多个向量字段,可在 MongoDB Shell 中执行以下脚本自动计算。
  • // 使用方法:将 <集合名称> 和 <向量字段名> 替换为实际值后执行
    var collName = "<集合名称>"; // 例如 "products"
    var fieldName = "<向量字段名>"; // 例如 "embedding"
    var sampleSize = 1000; // 采样数量,可根据数据规模调整
    var result = db.getCollection(collName).aggregate([
    { $sample: { size: sampleSize } },
    { $match: { [fieldName]: { $exists: true } } },
    {
    $group: {
    _id: null,
    avgDim: { $avg: { $size: "$" + fieldName } },
    count: { $sum: 1 }
    }
    }
    ]).toArray();
    if (result.length === 0) {
    print("未找到包含字段 " + fieldName + " 的文档,请检查字段名是否正确。");
    } else {
    var avgDim = result[0].avgDim;
    var sampledCount = result[0].count;
    var totalDocs = db.getCollection(collName).estimatedDocumentCount();
    var vectorSizeBytes = totalDocs * avgDim * 4;
    var vectorSizeGiB = vectorSizeBytes / (1024 * 1024 * 1024);
    print("===== 向量数据估算结果 =====");
    print("集合名称: " + collName);
    print("预计文档总数: " + totalDocs);
    print("采样文档数: " + sampledCount);
    print("平均向量维度: " + avgDim.toFixed(0));
    print("单条向量大小: " + (avgDim * 4 / 1024).toFixed(2) + " KiB");
    print("向量数据总大小: " + vectorSizeGiB.toFixed(2) + " GiB");
    }
  • 预期输出示例
  • ===== 向量数据估算结果 =====
    集合名称: products
    预计文档总数: 1000000
    采样文档数: 987
    平均向量维度: 1536
    单条向量大小: 6.00 KiB
    向量数据总大小: 5.72 GiB
说明
若集合中包含多个向量字段(如 title_embedding 和 image_embedding),请分别修改 fieldName 执行脚本,并将各字段的结果求和。
  1. 计算 mongot 索引所需磁盘空间
  • 获得向量数据总大小后,即可计算 mongot 所需的磁盘空间。
  • 请先确认您是否同时启用了全文搜索索引。启用与否对于计算 mongot 所需磁盘空间的差异如下:
  • 仅向量搜索:总磁盘需求 = 向量索引磁盘大小(阅读向量索引磁盘大小部分)
  • 向量搜索 + 全文搜索:总磁盘需求 = 向量索引磁盘大小 + 全文索引磁盘大小(阅读全部内容)
  • 向量索引磁盘大小
  • 向量索引磁盘大小 = 向量数据总大小 × 1.0(基线)
说明
上述公式计算的是向量索引的基础大小。HNSW(分层可导航小世界图)结构会产生额外的元数据开销,但通常较小。本文已在步骤 4 中通过 40% 的冗余空间统一覆盖这部分开销。
  • 全文索引磁盘大小(如适用)
  • 如果同时启用了全文搜索索引,需额外计算磁盘占用。
  • 全文索引磁盘大小 = 索引文本总大小 × 扩展系数
  1. 计算 mongot 索引所需内存
  • 磁盘规格确定后,接下来计算内存需求。总内存需求由以下三部分组成:
  • 总内存需求 = 向量索引内存 + JVM 堆内存 + 文件系统缓存
说明
文件系统缓存由操作系统自动管理,您需要主动规划的是向量索引内存JVM 堆内存
  • 向量索引内存
  • 向量索引所需内存 = 向量索引磁盘大小 × 1.25
说明
MongoDB 官方建议在索引大小基础上额外增加 20%~25% 的缓冲空间,用于 HNSW 图结构在内存中的运行时开销。因此系数为 1.25(即 100% + 25%)。详情请参见 mongot 部署的资源分配注意事项
  • 计算示例:向量索引磁盘大小为 5.72 GiB,则所需向量索引内存 = 5.72 × 1.25 = 7.15 GiB。
  • 通过向量量化降低内存需求
  • 当索引规模较大时,可通过向量量化将浮点向量(如 float32)压缩为低精度表示,以降低内存占用。MongoDB 支持的量化方式如下:
  • 量化方式
    内存缩减效果
    适用场景
    无量化
    1x(基线)
    对召回精度要求严格
    标量量化
    约 3.75 倍(即降至原来的 1/3.75,约 26.7%)
    精度与资源的平衡方案
    二进制量化
    约 24 倍(即降至原来的 1/24,约 4.2%)
    大规模、极致成本优化
注意
当向量索引磁盘大小超过 3 GiB 时,建议评估启用量化。详情请参见矢量量化
  1. 叠加安全余量,确定最终规格
  • 步骤 2 和步骤 3 计算的是当前负载所需的最小规格。在实际生产环境中,还需叠加安全余量以应对未来增长和运维操作。
  • 推荐磁盘空间 = mongot 总磁盘需求 ÷ 0.6
    推荐内存大小 = mongot 总内存需求 ÷ 0.6
  • 预留 40% 意味着当前负载只占最终规格的 60%。因此:最终规格 = 当前负载 ÷ 0.6。
  • 40% 余量的构成如下:
  • 余量项
    说明
    索引重建空间
    修改索引定义时需同时保留新旧两份索引,需额外空间。
    数据增长缓冲
    为业务数据的自然增长预留空间。
    运行时开销
    JVM 垃圾回收、文件系统缓存、操作系统等开销。
    只读保护阈值
    当磁盘利用率达到 90% 时 mongot 将进入只读状态。
说明
如果暂时无法精确估算,建议 mongot 存储空间与 mongod 的初始存储配置值保持一致,后续根据监控调整。
规格与选型参考
  • 规格速查表
说明
使用场景:您处于规划阶段,还没有精确的文档数量或向量维度数据,需要快速估算规格。
与精确计算的关系:如果您已经完成了步骤 1~4 的精确计算,请优先使用计算结果。速查表仅用于规划阶段的快速参考,两者可能存在差异。
  • 工作负载类型说明
  • 工作负载类型
    适用场景
    内存:CPU 比率
    说明
    低 CPU 工作负载
    向量搜索
    8:1
    向量搜索主要是内存中的向量比对,性能瓶颈通常在于内存带宽,而非 CPU 计算能力。
    高 CPU 工作负载
    全文搜索
    2:1
    全文搜索涉及文本分词、相关性评分等复杂计算,相对更消耗 CPU。
  • 向量搜索场景请选择低 CPU 工作负载
  • 规格选型步骤
  • 步骤 1:确定您的工作负载大小类别
  • 工作负载大小
    内存范围 (GiB)
    存储范围 (GiB)
    CPU 范围 (核)
    小型
    8~16
    50~100
    1~2
    中型
    32~64
    200~400
    4~8
    大型
    128~256
    800~1600
    16~32
  • 步骤 2:根据您的向量数据大小,在下表中找到对应配置
  • 下表将上述官方分类映射到具体的向量数据规模,方便您直接对号入座。
  • 向量数据大小
    对应工作负载大小
    推荐内存
    推荐磁盘
    典型场景
    < 1 GiB
    小型
    8~16 GiB
    50~100 GiB
    概念验证、小型知识库
    1~10 GiB
    中型
    32~64 GiB
    200~400 GiB
    推荐系统、中型 RAG
    10~50 GiB
    大型
    128~256 GiB
    800~1600 GiB
    大型搜索、企业级 RAG
    > 50 GiB
    分片集群 + 量化
    按分片数分配
    超大规模向量检索
说明
  • 上表基于纯向量搜索、未启用量化的场景。当向量数据总大小超过 10 GiB 时,建议启用量化以降低内存需求。
  • 规格调整是迭代过程,建议部署后根据实际监控持续优化。
完整估算示例
以下是一个中型电商推荐场景的完整计算过程。本示例与上文“规格速查表”中“中型(向量数据大小 1~10 GiB)”配置相对应,可作为精确计算的验证参考。
业务假设
  • 100 万条商品文档,每条包含 1536 维向量(OpenAI ada-002)
  • 同时启用全文搜索(标准分词,索引文本约 500 MiB)
  • 未启用量化
说明
示例 JVM 堆的确定逻辑
JVM 堆的大小取决于最终选择的内存规格,mongot 默认分配系统可用内存的 25% 给 JVM 堆。因此需要先假设一个规格,再验证是否够用。
本示例根据规格速查表“中型”的内存范围(32~64 GiB),取最低值 32 GiB 作为假设规格:
  • JVM 堆 = 32 × 25% = 8 GiB
  • 总内存需求 = 向量索引内存 7.15 GiB + JVM 堆 8 GiB = 15.15 GiB
  • 叠加 40% 余量:15.15 ÷ 0.6 = 25.25 GiB → 向上取整为 32 GiB
  • ✅ 验证通过:25.25 GiB ≤ 32 GiB
如果验证不通过,则需要换更大的规格(如 64 GiB)重新计算,直到验证通过。
详情请参见 mongot部署的硬件注意事项
计算项
结果
计算过程
步骤 1:向量数据总大小
5.72 GiB
1,000,000 × 1536 × 4 ÷ 1024³
步骤 2:mongot 总磁盘需求
6.72 GiB
向量索引磁盘大小 5.72 GiB + 全文索引磁盘大小(500 MiB × 2)
步骤 3:mongot 总内存需求
15.15 GiB
向量索引内存 7.15 GiB(5.72 × 1.25)+ JVM 堆 8 GiB(假设 32 GiB × 25%)
步骤 4:推荐磁盘(含 40% 余量)
≈ 11.2 GiB
6.72 ÷ 0.6
步骤 4:推荐内存(含 40% 余量)
≈ 25.25 GiB → 向上取整到 32 GiB
15.15 ÷ 0.6
副本集实例 vs 分片集群实例(3 个分片)对比:
计算项
副本集实例(单节点)
分片集群实例(单分片)
向量索引磁盘大小
5.72 GiB
≈ 1.91 GiB(5.72 ÷ 3)
mongot 总内存需求
15.15 GiB
≈ 5.05 GiB(15.15 ÷ 3)
推荐磁盘(含 40% 余量)
≈ 11.2 GiB
≈ 3.7 GiB(11.2 ÷ 3)
推荐内存(含 40% 余量)
≈ 25.25 GiB → 向上取整到 32 GiB
≈ 8.4 GiB (25.25 ÷ 3) → 向上取整
示例推荐配置:32 GiB 内存 / 200 GiB 磁盘 / 4 vCPU(来源:MongoDB 官方低 CPU 工作负载中型规格表,详见上方“规格速查表”的配置说明。4 vCPU 为中型规格下限,QPS > 100 时建议从 8 vCPU 起步。)
最近更新时间:2026.08.04 19:08:15
这个页面对您有帮助吗?
有用
有用
无用
无用