跳至主要內容

在向量資料庫儲存嵌入向量

產生嵌入向量後,你需要將它們儲存在支援向量相似度搜尋的資料庫中。Mastra 提供一致的介面,讓你可在不同向量資料庫中儲存及查詢嵌入向量。

支援的資料庫
支援的資料庫 的直接連結

vector-store.ts
import { MongoDBVector } from '@mastra/mongodb'

const store = new MongoDBVector({
id: 'mongodb-vector',
uri: process.env.MONGODB_URI,
dbName: process.env.MONGODB_DB_NAME,
})
await store.createIndex({
indexName: 'myCollection',
dimension: 1536,
})
await store.upsert({
indexName: 'myCollection',
vectors: embeddings,
metadata: chunks.map(chunk => ({ text: chunk.text })),
})

使用 MongoDB Atlas Vector Search

如需詳細設定指引及最佳做法,請參閱 MongoDB Atlas Vector Search 官方文件

配合 MongoDB 使用 VoyageAI

MongoDB 可與針對檢索工作最佳化的 VoyageAI 嵌入模型無縫配合。如需完整範例及專用模型,請參閱 VoyageAI 嵌入向量文件MongoDB 向量參考

混合搜尋(向量 + 全文)

MongoDB 支援混合搜尋,透過伺服器端的 $rankFusion 融合向量相似度與 BM25 全文搜尋(需要 MongoDB >= 8.0;由 8.1 起正式提供,並已在 Atlas 8.0.x 啟用)。當你想結合語義及關鍵字檢索時,這項功能非常實用:

await store.createSearchIndex({ indexName: 'myCollection', fields: ['text'] })
const results = await store.hybridQuery({
indexName: 'myCollection',
queryVector: embedding,
query: 'search terms',
paths: ['text'],
topK: 10,
})

有關 createSearchIndex()textQuery()hybridQuery() 的詳情,請參閱 MongoDB 向量參考

使用向量儲存
使用向量儲存 的直接連結

初始化後,所有向量儲存均使用相同介面來建立索引、upsert 嵌入向量及進行查詢。

建立索引
建立索引 的直接連結

儲存嵌入向量前,你需要建立維度大小與嵌入模型相符的索引:

store-embeddings.ts
// Create an index with dimension 1536 (for text-embedding-3-small)
await store.createIndex({
indexName: 'myCollection',
dimension: 1536,
})

維度大小必須與所選嵌入模型的輸出維度相符。常見維度大小包括:

  • OpenAI text-embedding-3-small:1536 維(或自訂,例如 256)
  • Cohere embed-multilingual-v3:1024 維
  • VoyageAI voyage-3.5:1024 維(或自訂為 256、512、1024、2048)
  • Google gemini-embedding-001:768 維(或自訂)
注意

索引建立後便無法變更維度。如要使用其他模型,請刪除索引,然後以新的維度大小重新建立。

資料庫命名規則
資料庫命名規則 的直接連結

每個向量資料庫都會對索引及集合套用特定命名慣例,以確保兼容性並避免衝突。

集合(索引)名稱必須:

  • 以字母或底線開頭
  • 長度不超過 120 位元組
  • 只包含字母、數字、底線或句點
  • 不可包含 $ 或空字符
  • 範例:my_collection.123 有效
  • 範例:my-index 無效(包含連字號)
  • 範例:My$Collection 無效(包含 $

Upsert 嵌入向量
Upsert 嵌入向量 的直接連結

建立索引後,你可以將嵌入向量連同其基本元資料一起儲存:

store-embeddings.ts
// Store embeddings with their corresponding metadata
await store.upsert({
indexName: 'myCollection', // index name
vectors: embeddings, // array of embedding vectors
metadata: chunks.map(chunk => ({
text: chunk.text, // The original text content
id: chunk.id, // Optional unique identifier
})),
})

upsert 操作會:

  • 接收嵌入向量陣列及其對應的元資料
  • 如向量使用相同 ID,便更新現有向量
  • 如向量尚未存在,便建立新向量
  • 自動分批處理大型資料集

加入元資料
加入元資料 的直接連結

向量儲存支援豐富的元資料(任何可序列化為 JSON 的欄位),以供篩選及整理。由於元資料不採用固定結構描述,請使用一致的欄位命名,以免查詢結果不符合預期。

注意

元資料對向量儲存非常重要。沒有元資料,你只會有數值嵌入向量,無法傳回原文或篩選結果。請至少將來源文字儲存為元資料。

// Store embeddings with rich metadata for better organization and filtering
await store.upsert({
indexName: 'myCollection',
vectors: embeddings,
metadata: chunks.map(chunk => ({
// Basic content
text: chunk.text,
id: chunk.id,

// Document organization
source: chunk.source,
category: chunk.category,

// Temporal metadata
createdAt: new Date().toISOString(),
version: '1.0',

// Custom fields
language: chunk.language,
author: chunk.author,
confidenceScore: chunk.score,
})),
})

元資料的主要注意事項:

  • 嚴格統一欄位命名——例如 'category' 與 'Category' 不一致會影響查詢
  • 只加入你打算用於篩選或排序的欄位——額外欄位會增加負擔
  • 加入時間戳記(例如 'createdAt'、'lastUpdated')以追蹤內容時效

刪除向量
刪除向量 的直接連結

建構 RAG 應用程式時,文件遭刪除或更新後,通常需要清理過時向量。Mastra 提供 deleteVectors 方法,支援按元資料篩選條件刪除向量,讓你輕鬆移除與特定文件相關的所有嵌入向量。

按元資料篩選條件刪除
按元資料篩選條件刪除 的直接連結

最常見的使用情境,是在使用者刪除特定文件時,同時刪除該文件的所有向量:

delete-vectors.ts
// Delete all vectors for a specific document
await store.deleteVectors({
indexName: 'myCollection',
filter: { docId: 'document-123' },
})

這在以下情況特別實用:

  • 使用者刪除文件,而你需要移除其所有區塊
  • 你正為文件重新建立索引,並希望先移除舊向量
  • 你需要清理特定使用者或租戶的向量

刪除多份文件
刪除多份文件 的直接連結

你亦可使用複合篩選條件,刪除符合多項條件的向量:

delete-vectors-advanced.ts
// Delete all vectors for multiple documents
await store.deleteVectors({
indexName: 'myCollection',
filter: {
docId: { $in: ['doc-1', 'doc-2', 'doc-3'] },
},
})

// Delete vectors for a specific user's documents
await store.deleteVectors({
indexName: 'myCollection',
filter: {
$and: [{ userId: 'user-123' }, { status: 'archived' }],
},
})

按向量 ID 刪除
按向量 ID 刪除 的直接連結

如要刪除特定向量 ID,可直接傳入這些 ID:

delete-by-ids.ts
// Delete specific vectors by their IDs
await store.deleteVectors({
indexName: 'myCollection',
ids: ['vec-1', 'vec-2', 'vec-3'],
})

最佳做法
最佳做法 的直接連結

  • 大量插入前先建立索引
  • 大量插入時使用批次操作(upsert 方法會自動分批處理)
  • 只儲存你會用於查詢的元資料
  • 確保嵌入向量維度與模型相符(例如 text-embedding-3-small 使用 1536 維)