メインコンテンツへ移動

ベクトルデータベースへの埋め込みの保存

埋め込みを生成したら、ベクトル類似性検索に対応するデータベースへ保存する必要があります。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 バイト以内にする
  • 英字、数字、アンダースコア、ドットのみを使用する
  • $ または null 文字を含めない
  • 例: 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 が分かっている場合は、直接渡せます。

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)