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 索引并执行检索查询。​
创建向量索引时,如何选择向量化方式(手动 vs 自动)?​
核心判断依据是您是否已有向量生成管线(即生成并维护向量的整套流程),以及是否需要自行维护向量生成与同步。手动方式适合已有自建模型或第三方向量管线的场景;自动方式适合希望快速搭建、不想维护向量生成链路的场景。具体对比如下。​
​
对比项​
手动​
自动​
向量生成​
自行使用嵌入模型生成向量,存储到集合字段中​
系统自动调用方舟 Embedding 模型生成向量​
模型来源​
自由选择任意嵌入模型​
​
使用方舟提供的模型,当前仅支持 Doubao-embedding-vision,具体以控制台为准​
数据同步​
自行维护向量与源数据一致​
系统通过变更监听机制自动增量向量化,无需业务侧轮询或手动触发​
开发门槛​
较高,需编写程序调用模型 API、维护同步逻辑​
较低,控制台配置源文本字段即可,全托管​
​
注意​
  • 查询时使用的嵌入模型须与索引时一致,否则检索结果不准确。​
  • 选择手动方式时,需自行保证文档更新后向量字段同步更新;选择自动方式则无需考虑此问题。​
  • 使用自动方式前,需确保已开通方舟向量模型服务并获取 API Key。具体操作步骤,请参见获取方舟 API Key。​
如何选择相似度计算方式?​
在创建 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)。​
  • 启用量化(scalar 或 binary)可以解决预过滤查询的内存问题,而无需增加更多内存。​
建议将选择性高(即不同值较多的字段,如 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.10.13 19:43:53
这个页面对您有帮助吗?
有用
有用
无用
无用