跳至主要内容

掌握 MongoDB 向量搜索:实用指南与示例

了解如何设置并使用 MongoDB 的向量搜索来构建智能应用。本实用指南涵盖向量索引、查询最佳实践以及真实案例。
· 7分钟 阅读

使用 AI 探索

向量索引已成为构建现代应用的强大工具。它使您能够对高维数据执行快速高效的相似度搜索,这些高维数据通常被称为向量嵌入。这一能力现已无缝集成至 MongoDB,开发者可以直接在数据库中构建复杂功能。

本文将以实践为导向,手把手带您在 MongoDB 中设置并使用向量索引。从创建第一个索引到运行复杂查询,我们将逐步讲解。您还将学习最佳实践,并通过一个电商商店的产品推荐系统这一真实案例来加深理解。

什么是向量索引?

从本质上讲,向量索引是一种组织向量嵌入以加速相似度搜索的技术。与作用于标量值(如数字或字符串)的传统索引不同,向量索引针对在多维空间中查找“相邻”向量进行了优化。

向量嵌入是对复杂数据(包括文本、图像和音频)的数值化表示。例如,一段产品描述可以被转换为一个向量,类似产品的向量会在空间中彼此更接近。这种距离上的接近性使以下应用成为可能:

  • 语义搜索:基于查询的含义查找产品,而非仅仅匹配关键词。
  • 推荐系统:根据用户偏好为其推荐产品或内容。
  • 图像识别:从大型数据库中识别相似图像。

在 MongoDB 中设置向量索引

开始之前,您需要一个 MongoDB Atlas 集群。向量搜索是云原生功能。您可以在 MongoDB Atlas 或免费的Community edition中试用该功能。本文将使用 MongoDB Atlas。

步骤 1:创建 MongoDB Atlas 集群 

在 MongoDB Atlas 中创建一个新集群。免费 M0 层足以用于测试。

步骤 2:创建集合并插入数据 

首先,使用 MongoDB Shell(mongosh)或您偏好的驱动程序连接到集群。然后创建名为products的新集合,并插入包含向量字段的文档。每个文档应表示一个产品,并包含一个embedding字段,用于存放该产品的向量表示。

下面是一个更完整的示例,包含三个不同的产品文档,每个都带有一个随机生成的向量,以演示数据可能的结构。在真实场景中,您会将其替换为由 AI 模型生成的嵌入。

db.products.insertMany([
  {
    "name": "Wireless Noise-Canceling Headphones",
    "category": "Electronics",
    "description": "Premium over-ear headphones with active noise cancellation and a 30-hour battery life.",
    "price": 249.99,
    "embedding": [0.012, 0.054, 0.089, -0.031, 0.067, 0.021, -0.045, 0.098, 0.011, -0.076, 0.033, -0.015, -0.087, 0.059, 0.009, 0.042]
  },
  {
    "name": "Smart Coffee Maker",
    "category": "Home Goods",
    "description": "Programmable coffee machine that can be controlled from your smartphone. Brews up to 12 cups.",
    "price": 129.99,
    "embedding": [0.056, 0.023, 0.011, 0.078, -0.029, 0.041, 0.087, -0.019, 0.065, 0.002, -0.093, 0.018, 0.057, -0.041, 0.022, 0.064]
  },
  {
    "name": "Ultra-light Backpack",
    "category": "Travel",
    "description": "Durable and lightweight backpack with multiple compartments, perfect for hiking or daily commutes.",
    "price": 79.99,
    "embedding": [-0.072, 0.034, 0.019, 0.068, -0.055, 0.081, 0.004, -0.025, 0.039, 0.016, -0.044, 0.062, 0.008, 0.071, -0.013, 0.053]
  }
]);

每个文档都包含name、category、description和price,以及关键的embedding字段。该embedding是一个固定大小的数字数组,表示产品描述的语义含义。该数组的大小,即维度,取决于用于生成嵌入的模型。在本示例中,维度为 128。

我们将在这些数据之上构建向量索引,以实现语义搜索和产品推荐。

步骤 3:创建向量索引

当集合中已有带嵌入的数据后,下一步就是创建向量索引。该索引对于实现快速高效的相似度搜索至关重要。下面的命令使用createSearchIndex在embedding字段上构建向量索引。

db.products.createSearchIndex({
  "name": "vector_index",
  "definition": {
    "mappings": {
      "dynamic": true,
      "fields": [
        {
          "type": "vector",
          "path": "embedding",
          "numDimensions": 128, 
          "similarity": "cosine"
        }
      ]
    },
  }
});

理解配置

索引配置定义在definition对象的fields数组内。该结构是 MongoDB Atlas 组织向量以实现高速检索的蓝图。

向量索引的核心参数包括:

  • path:指定文档中存放向量数组的字段名,本例为"embedding"。
  • numDimensions:这是最关键的参数,必须与您的嵌入模型产生的向量数组元素个数完全一致(例如 128、768、1536)。
  • similarity:定义搜索时用于计算两个向量“接近程度”的数学度量。
    • cosine通常推荐用于语义搜索,因为它测量向量之间的夹角,侧重语义方向。
    • 其他选项包括euclidean(直线距离)和dotProduct。

可选性能参数

对于高级性能调优,MongoDB Atlas 允许您指定可选参数以优化存储与内存:

  • quantization:用于压缩向量,可显著减少索引大小和内存占用。
    • scalar或binary可用于量化向量,在略微牺牲召回率的前提下,显著提升存储效率与速度。

执行向量搜索查询

索引构建完成后,您可以使用$vectorSearch 聚合阶段来执行相似度查询。

让我们查找与某个查询向量最相似的产品。该查询通常由用户的搜索输入生成。

// A sample query vector, generated from a user's search for "wireless audio device"
const queryVector = [0.11, 0.22, 0.33, ...];

db.products.aggregate([
  {
    "$vectorSearch": {
      "queryVector": queryVector,
      "path": "embedding",
      "numCandidates": 100, // Number of documents to scan
      "limit": 5 // Number of results to return
    }
  },
  {
    "$project": {
      "name": 1,
      "description": 1,
      "_id": 0
    }
  }
]);
  • queryVector:要搜索的向量。
  • path:包含向量嵌入的字段名。
  • numCandidates:在索引中扫描的候选文档数量。数值越高,准确性越好,但延迟也会增加。
  • limit:返回的结果数量上限。

可选的$project阶段有助于整理输出,并从结果中排除向量数据。

向量索引的最佳实践

在为最佳性能调优向量索引时,您需要在准确性与速度之间取得平衡。关键在于根据您的特定数据集和性能目标来调整索引参数。

选择合适的相似度度量

度量的选择至关重要,因为它定义了两个向量的“相似”程度。您可以参考 MongoDB 文档以进一步了解这些字段。

  • cosine:最适合语义相似性,尤其是文本。它测量向量间的夹角,忽略长度。这对向量长度无实际意义的模型至关重要。
  • euclidean:测量两向量之间的直线距离。如果向量的大小(长度)对其含义很重要(例如某些数据类型中更大值表示更强特征),可使用该度量。
  • dotProduct:计算两个向量的点积。该度量常用于推荐系统。当向量嵌入被归一化为长度 1 时,点积在功能上等同于余弦相似度。

管理嵌入维度

参数dimensions至关重要,并且必须与您的嵌入模型的输出完全一致。一个常见错误是选择与模型输出不匹配的数字。维度更高的模型能捕捉更多细节,但索引会更大,查询可能变慢。务必查阅模型文档以确认其维度(例如 OpenAI 的text-embedding-ada-002输出 1536 维)。

索引调优

参数numCandidates和numLists对于在速度与准确性之间取得平衡至关重要。一个不错的经验法则是从较低的numCandidates开始,逐步增加,直到达到满意的准确度。对于ivf索引,您也可以尝试不同的numLists,以找到最适合您数据集的平衡点。

示例用例:构建简单推荐系统

让我们将这些概念应用到一个实践示例:电商产品推荐系统。

步骤 1:存储带有嵌入的产品数据

首先,我们将存储产品名称、类别以及各自的向量嵌入。嵌入可以根据产品描述或特性生成。

db.products.insertMany([
  {
    "name": "Smart Speaker",
    "category": "Electronics",
    "embedding": [0.8, 0.9, 0.1, ...]
  },
  {
    "name": "Wireless Earbuds",
    "category": "Electronics",
    "embedding": [0.7, 0.8, 0.2, ...]
  },
  {
    "name": "Leather Wallet",
    "category": "Fashion",
    "embedding": [0.1, 0.2, 0.9, ...]
  }
]);

步骤 2:在embedding上创建向量索引

db.products.createSearchIndex({
  "name": "vector_index",
  "definition": {
    "mappings": {
      "fields": [
        {
          "type": "vector",
          "path": "embedding", // The field containing the vectors
          "numDimensions": 128, // The correct field name is 'numDimensions'
          "similarity": "cosine" // The correct field name is 'similarity'
          // Index algorithm (like HNSW) is managed automatically by Atlas
        }
      ]
    }
  }
});

步骤 3:查询相似产品

现在,让我们查找与 Smart Speaker 相似的产品。我们将使用 Smart Speaker 的嵌入作为查询向量。

const smartSpeakerEmbedding = [0.8, 0.9, 0.1, ...];

db.products.aggregate([
  {
    "$vectorSearch": {
      "queryVector": smartSpeakerEmbedding,
      "path": "embedding",
      "numCandidates": 50,
      "limit": 3
    }
  },
  {
    "$project": {
      "name": 1,
      "category": 1,
      "_id": 0
    }
  }
]);

此查询将返回与 Smart Speaker 的向量嵌入最接近的前三个产品,从而有效推荐类似商品,例如 Wireless Earbuds。

总结

MongoDB 的向量搜索能力为构建智能且个性化的应用打开了新的可能。通过将向量索引直接集成到数据库中,MongoDB 简化了整体架构,使数据管理更轻松,相似度搜索更快速。

借助向量搜索,您可以超越简单的关键词匹配,打造能够理解数据上下文与含义的功能。我们鼓励您从MongoDB Atlas 免费层开始试验,探索向量索引如何增强您的应用。

FAQs

什么是向量嵌入?为什么向量搜索需要它?

向量嵌入是对文本或图像等数据的数值化表示。它之所以对向量搜索必不可少,是因为数据库可以通过计算向量间的距离来衡量项目的语义相似度,从而超越简单的关键词匹配。

使用向量搜索需要特定的 MongoDB 版本吗?

是的。向量搜索是MongoDB Atlas(MongoDB 的云托管版本)的集成功能。在社区版或本地部署版中不可用。

我需要自己生成向量嵌入吗?

需要。在将数据存储到 MongoDB 并创建向量索引之前,您需要先为数据生成向量嵌入。MongoDB 不会替您生成这些嵌入。通常,您会使用第三方服务或来自OpenAI、Hugging Face或Google AI等平台的预训练模型,将文本、图像或其他数据转换为数值向量。

我可以将向量搜索与其他 MongoDB 查询结合使用吗?

可以。向量搜索是一个聚合阶段($vectorSearch),这意味着您可以在更大的 MongoDB 聚合管道中使用它。这样就能将向量搜索与 $match、$project、$limit 和 $lookup 等强大阶段组合起来,在一次操作中完成过滤、排序和数据富化。这一能力称为混合搜索,对构建真实世界的应用至关重要。

IVF 和 HNSW 索引类型有何区别?

IVF 和 HNSW 都是用于近似最近邻(ANN)搜索的算法。它们的主要区别在于数据组织方式不同。

Karen Zhang

作者

Karen Zhang

Karen 是一名数据工程师,热衷于构建可扩展的数据平台。她拥有使用 Terraform 进行基础设施自动化的经验,并很乐于通过博客文章和教程分享她的所学。Karen 也是一位社区建设者,热衷于促进数据专业人士之间的联结。

主题