Menu
Back to Blog
1 min read
KI-Entwicklung

MongoDB Atlas Vector Search für AI-Anwendungen

MongoDB Atlas Vector Search für semantische Suche und RAG. Embedding API, Hybrid Queries und Integration mit LLMs.

MongoDB AtlasVector SearchSemantic SearchRAGEmbeddingsAI Database
MongoDB Atlas Vector Search für AI-Anwendungen

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

// 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

// 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"
      }
    ]
  }
}
// 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

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

// 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

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

// 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)

// 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