- Add 100 blog posts covering AI, development, and tech topics - Add .env.example for environment configuration - Add accessibility and lighthouse audit scripts - Remove obsolete SEO reports and temporary files - Remove dev-dist build artifacts and backup files - Remove unused portrait images (moved/consolidated elsewhere) - Update contact form and component improvements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
501 lines
12 KiB
Markdown
501 lines
12 KiB
Markdown
# MongoDB Atlas Vector Search für AI-Anwendungen
|
||
|
||
**Meta-Description:** MongoDB Atlas Vector Search für semantische Suche und RAG. Embedding API, Hybrid Queries und Integration mit LLMs.
|
||
|
||
**Keywords:** MongoDB Atlas, Vector Search, Semantic Search, RAG, Embeddings, AI Database, LLM Integration
|
||
|
||
---
|
||
|
||
## Einführung
|
||
|
||
MongoDB Atlas bietet mit **Vector Search** eine native Lösung für AI-Anwendungen. Operative Daten und Vector Embeddings in einer Datenbank – ohne Sync-Probleme zwischen separaten Systemen.
|
||
|
||
---
|
||
|
||
## Vector Search Architecture
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ MONGODB ATLAS VECTOR SEARCH │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ │
|
||
│ Single Platform: │
|
||
│ ├── Operative Daten (Documents) │
|
||
│ ├── Vector Embeddings (1536+ Dimensions) │
|
||
│ ├── Metadata (für Filtering) │
|
||
│ └── Full-Text Search (Atlas Search) │
|
||
│ │
|
||
│ Vector Index Types: │
|
||
│ ├── HNSW (Hierarchical Navigable Small World) │
|
||
│ ├── IVF (Inverted File Index) │
|
||
│ └── Vector Quantization (Cost Reduction) │
|
||
│ │
|
||
│ Use Cases: │
|
||
│ ├── Semantic Search │
|
||
│ ├── RAG (Retrieval-Augmented Generation) │
|
||
│ ├── Recommendation Systems │
|
||
│ └── Image/Audio Similarity │
|
||
│ │
|
||
│ Performance (Dedicated Search Nodes): │
|
||
│ └── 40-60% schnellere Query Times │
|
||
│ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## Setup
|
||
|
||
```typescript
|
||
// lib/mongodb.ts
|
||
import { MongoClient } from 'mongodb';
|
||
|
||
const uri = process.env.MONGODB_URI!;
|
||
const options = {};
|
||
|
||
let client: MongoClient;
|
||
let clientPromise: Promise<MongoClient>;
|
||
|
||
if (process.env.NODE_ENV === 'development') {
|
||
const globalWithMongo = global as typeof globalThis & {
|
||
_mongoClientPromise?: Promise<MongoClient>;
|
||
};
|
||
|
||
if (!globalWithMongo._mongoClientPromise) {
|
||
client = new MongoClient(uri, options);
|
||
globalWithMongo._mongoClientPromise = client.connect();
|
||
}
|
||
clientPromise = globalWithMongo._mongoClientPromise;
|
||
} else {
|
||
client = new MongoClient(uri, options);
|
||
clientPromise = client.connect();
|
||
}
|
||
|
||
export default clientPromise;
|
||
```
|
||
|
||
---
|
||
|
||
## Vector Index erstellen
|
||
|
||
```javascript
|
||
// Atlas Search Index Definition (JSON)
|
||
{
|
||
"name": "vector_index",
|
||
"type": "vectorSearch",
|
||
"definition": {
|
||
"fields": [
|
||
{
|
||
"type": "vector",
|
||
"path": "embedding",
|
||
"numDimensions": 1536,
|
||
"similarity": "cosine"
|
||
},
|
||
{
|
||
"type": "filter",
|
||
"path": "category"
|
||
},
|
||
{
|
||
"type": "filter",
|
||
"path": "createdAt"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
```typescript
|
||
// Programmatisch Index erstellen
|
||
import { MongoClient } from 'mongodb';
|
||
|
||
async function createVectorIndex() {
|
||
const client = await MongoClient.connect(process.env.MONGODB_URI!);
|
||
const db = client.db('myapp');
|
||
|
||
await db.command({
|
||
createSearchIndexes: 'documents',
|
||
indexes: [
|
||
{
|
||
name: 'vector_index',
|
||
type: 'vectorSearch',
|
||
definition: {
|
||
fields: [
|
||
{
|
||
type: 'vector',
|
||
path: 'embedding',
|
||
numDimensions: 1536,
|
||
similarity: 'cosine'
|
||
}
|
||
]
|
||
}
|
||
}
|
||
]
|
||
});
|
||
|
||
await client.close();
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Documents mit Embeddings speichern
|
||
|
||
```typescript
|
||
import OpenAI from 'openai';
|
||
import clientPromise from '@/lib/mongodb';
|
||
|
||
const openai = new OpenAI();
|
||
|
||
interface Document {
|
||
_id?: string;
|
||
title: string;
|
||
content: string;
|
||
embedding: number[];
|
||
category: string;
|
||
createdAt: Date;
|
||
}
|
||
|
||
// Embedding generieren
|
||
async function generateEmbedding(text: string): Promise<number[]> {
|
||
const response = await openai.embeddings.create({
|
||
model: 'text-embedding-ada-002',
|
||
input: text
|
||
});
|
||
return response.data[0].embedding;
|
||
}
|
||
|
||
// Document speichern
|
||
async function saveDocument(
|
||
title: string,
|
||
content: string,
|
||
category: string
|
||
): Promise<Document> {
|
||
const client = await clientPromise;
|
||
const db = client.db('myapp');
|
||
|
||
// Embedding für Titel + Content
|
||
const embedding = await generateEmbedding(`${title}\n\n${content}`);
|
||
|
||
const document: Document = {
|
||
title,
|
||
content,
|
||
embedding,
|
||
category,
|
||
createdAt: new Date()
|
||
};
|
||
|
||
const result = await db.collection<Document>('documents').insertOne(document);
|
||
return { ...document, _id: result.insertedId.toString() };
|
||
}
|
||
|
||
// Bulk Import
|
||
async function bulkImportDocuments(docs: Array<{ title: string; content: string; category: string }>) {
|
||
const client = await clientPromise;
|
||
const db = client.db('myapp');
|
||
|
||
const documentsWithEmbeddings = await Promise.all(
|
||
docs.map(async (doc) => ({
|
||
...doc,
|
||
embedding: await generateEmbedding(`${doc.title}\n\n${doc.content}`),
|
||
createdAt: new Date()
|
||
}))
|
||
);
|
||
|
||
await db.collection('documents').insertMany(documentsWithEmbeddings);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Vector Search Queries
|
||
|
||
```typescript
|
||
// Basic Vector Search
|
||
async function searchDocuments(query: string, limit: number = 5) {
|
||
const client = await clientPromise;
|
||
const db = client.db('myapp');
|
||
|
||
const queryEmbedding = await generateEmbedding(query);
|
||
|
||
const results = await db.collection('documents').aggregate([
|
||
{
|
||
$vectorSearch: {
|
||
index: 'vector_index',
|
||
path: 'embedding',
|
||
queryVector: queryEmbedding,
|
||
numCandidates: 100,
|
||
limit: limit
|
||
}
|
||
},
|
||
{
|
||
$project: {
|
||
_id: 1,
|
||
title: 1,
|
||
content: 1,
|
||
category: 1,
|
||
score: { $meta: 'vectorSearchScore' }
|
||
}
|
||
}
|
||
]).toArray();
|
||
|
||
return results;
|
||
}
|
||
|
||
// Vector Search mit Filter
|
||
async function searchByCategory(
|
||
query: string,
|
||
category: string,
|
||
limit: number = 5
|
||
) {
|
||
const client = await clientPromise;
|
||
const db = client.db('myapp');
|
||
|
||
const queryEmbedding = await generateEmbedding(query);
|
||
|
||
const results = await db.collection('documents').aggregate([
|
||
{
|
||
$vectorSearch: {
|
||
index: 'vector_index',
|
||
path: 'embedding',
|
||
queryVector: queryEmbedding,
|
||
filter: {
|
||
category: category
|
||
},
|
||
numCandidates: 100,
|
||
limit: limit
|
||
}
|
||
},
|
||
{
|
||
$project: {
|
||
title: 1,
|
||
content: 1,
|
||
score: { $meta: 'vectorSearchScore' }
|
||
}
|
||
}
|
||
]).toArray();
|
||
|
||
return results;
|
||
}
|
||
|
||
// Hybrid Search (Vector + Full-Text)
|
||
async function hybridSearch(query: string, limit: number = 10) {
|
||
const client = await clientPromise;
|
||
const db = client.db('myapp');
|
||
|
||
const queryEmbedding = await generateEmbedding(query);
|
||
|
||
const results = await db.collection('documents').aggregate([
|
||
{
|
||
$vectorSearch: {
|
||
index: 'vector_index',
|
||
path: 'embedding',
|
||
queryVector: queryEmbedding,
|
||
numCandidates: 150,
|
||
limit: 50
|
||
}
|
||
},
|
||
{
|
||
$addFields: {
|
||
vectorScore: { $meta: 'vectorSearchScore' }
|
||
}
|
||
},
|
||
{
|
||
$unionWith: {
|
||
coll: 'documents',
|
||
pipeline: [
|
||
{
|
||
$search: {
|
||
index: 'text_index',
|
||
text: {
|
||
query: query,
|
||
path: ['title', 'content']
|
||
}
|
||
}
|
||
},
|
||
{
|
||
$addFields: {
|
||
textScore: { $meta: 'searchScore' }
|
||
}
|
||
},
|
||
{ $limit: 50 }
|
||
]
|
||
}
|
||
},
|
||
{
|
||
$group: {
|
||
_id: '$_id',
|
||
title: { $first: '$title' },
|
||
content: { $first: '$content' },
|
||
vectorScore: { $max: '$vectorScore' },
|
||
textScore: { $max: '$textScore' }
|
||
}
|
||
},
|
||
{
|
||
$addFields: {
|
||
combinedScore: {
|
||
$add: [
|
||
{ $ifNull: ['$vectorScore', 0] },
|
||
{ $multiply: [{ $ifNull: ['$textScore', 0] }, 0.5] }
|
||
]
|
||
}
|
||
}
|
||
},
|
||
{ $sort: { combinedScore: -1 } },
|
||
{ $limit: limit }
|
||
]).toArray();
|
||
|
||
return results;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## RAG Implementation
|
||
|
||
```typescript
|
||
import OpenAI from 'openai';
|
||
|
||
const openai = new OpenAI();
|
||
|
||
async function ragQuery(userQuestion: string) {
|
||
// 1. Relevante Dokumente finden
|
||
const relevantDocs = await searchDocuments(userQuestion, 5);
|
||
|
||
// 2. Context aufbauen
|
||
const context = relevantDocs
|
||
.map(doc => `Title: ${doc.title}\nContent: ${doc.content}`)
|
||
.join('\n\n---\n\n');
|
||
|
||
// 3. LLM mit Context aufrufen
|
||
const response = await openai.chat.completions.create({
|
||
model: 'gpt-4-turbo-preview',
|
||
messages: [
|
||
{
|
||
role: 'system',
|
||
content: `Du bist ein hilfreicher Assistent. Beantworte Fragen basierend auf dem folgenden Kontext. Wenn der Kontext die Antwort nicht enthält, sage das ehrlich.
|
||
|
||
Kontext:
|
||
${context}`
|
||
},
|
||
{
|
||
role: 'user',
|
||
content: userQuestion
|
||
}
|
||
],
|
||
temperature: 0.7,
|
||
max_tokens: 1000
|
||
});
|
||
|
||
return {
|
||
answer: response.choices[0].message.content,
|
||
sources: relevantDocs.map(d => ({
|
||
title: d.title,
|
||
score: d.score
|
||
}))
|
||
};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Automated Embedding mit Voyage AI
|
||
|
||
```typescript
|
||
// MongoDB Atlas Embedding API (Preview)
|
||
// Automatisches Embedding ohne eigene OpenAI-Calls
|
||
|
||
// Index Definition mit Auto-Embedding
|
||
{
|
||
"name": "auto_vector_index",
|
||
"type": "vectorSearch",
|
||
"definition": {
|
||
"fields": [
|
||
{
|
||
"type": "vector",
|
||
"path": "embedding",
|
||
"numDimensions": 1024,
|
||
"similarity": "cosine"
|
||
}
|
||
],
|
||
"embeddingModel": {
|
||
"name": "voyage-3",
|
||
"inputType": "document",
|
||
"fieldMappings": [
|
||
{
|
||
"source": "content",
|
||
"target": "embedding"
|
||
}
|
||
]
|
||
}
|
||
}
|
||
}
|
||
|
||
// Documents ohne manuelles Embedding speichern
|
||
async function saveDocumentAutoEmbed(title: string, content: string) {
|
||
const client = await clientPromise;
|
||
const db = client.db('myapp');
|
||
|
||
// Embedding wird automatisch generiert!
|
||
await db.collection('documents').insertOne({
|
||
title,
|
||
content,
|
||
createdAt: new Date()
|
||
});
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Vector Quantization (Kostenoptimierung)
|
||
|
||
```javascript
|
||
// Index mit Quantization für große Datasets
|
||
{
|
||
"name": "quantized_vector_index",
|
||
"type": "vectorSearch",
|
||
"definition": {
|
||
"fields": [
|
||
{
|
||
"type": "vector",
|
||
"path": "embedding",
|
||
"numDimensions": 1536,
|
||
"similarity": "cosine",
|
||
"quantization": {
|
||
"type": "scalar" // Reduziert Speicher um ~75%
|
||
}
|
||
}
|
||
]
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Fazit
|
||
|
||
MongoDB Atlas Vector Search bietet:
|
||
|
||
1. **Unified Platform**: Operative Daten + Vectors in einer DB
|
||
2. **Hybrid Search**: Kombination von Vector + Full-Text
|
||
3. **Auto-Embedding**: Voyage AI Integration für automatische Embeddings
|
||
4. **Skalierbarkeit**: Milliarden Vectors mit Quantization
|
||
|
||
Ideal für AI-Features in bestehenden MongoDB-Anwendungen.
|
||
|
||
---
|
||
|
||
## Bildprompts
|
||
|
||
1. "Vector embeddings flowing into search results, semantic similarity visualization"
|
||
2. "MongoDB document with vector arrows connecting similar documents"
|
||
3. "RAG pipeline showing document retrieval and LLM generation, AI workflow"
|
||
|
||
---
|
||
|
||
## Quellen
|
||
|
||
- [MongoDB Atlas Vector Search](https://www.mongodb.com/products/platform/atlas-vector-search)
|
||
- [MongoDB Vector Search Overview](https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-overview/)
|
||
- [MongoDB Embedding API](https://www.mongodb.com/company/blog/product-release-announcements/introducing-the-embedding-and-reranking-api-on-mongodb-atlas)
|
||
- [Vector Databases for LLM 2026](https://www.secondtalent.com/resources/top-vector-databases-for-llm-applications/)
|