MongoDB ist eine dokumentenorientierte NoSQL-Datenbank, die Daten als flexible JSON-ähnliche Dokumente statt in Zeilen und Spalten speichert. Während relationale Datenbanken ein vorab definiertes Schema verlangen und bei Änderungen Tabellenmigrationen erfordern, kann in MongoDB jedes Dokument einer Collection andere Felder enthalten — ideal für Anwendungen mit sich schnell ändernden Datenstrukturen. Dieser Leitfaden behandelt MongoDB-Installation, grundlegende CRUD-Operationen, Indizierungsstrategien und die Konfiguration eines Replica Sets für Produktivumgebungen.
Voraussetzungen
- Ein Linux-Server (Ubuntu 22.04 oder RHEL 8+ empfohlen) mit mindestens 2 GB RAM
- Root- oder sudo-Zugang für die Installation
- Grundlegende Kenntnisse des JSON-Datenformats
- Vertrautheit mit Kommandozeilenwerkzeugen
MongoDB installieren
Ubuntu/Debian
# MongoDB-GPG-Schlüssel importieren
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
# Repository hinzufügen
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-7.0.gpg ] \
https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
# MongoDB installieren
sudo apt update
sudo apt install -y mongodb-org
# Dienst starten und automatisch aktivieren
sudo systemctl start mongod
sudo systemctl enable mongod
# Prüfen ob der Dienst läuft
sudo systemctl status mongod
mongosh --eval "db.version()"
RHEL/CentOS
# Repository-Datei anlegen
cat <<'EOF' | sudo tee /etc/yum.repos.d/mongodb-org-7.0.repo
[mongodb-org-7.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/7.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-7.0.asc
EOF
sudo dnf install -y mongodb-org
sudo systemctl start mongod
sudo systemctl enable mongod
Docker
docker run -d \
--name mongodb \
-p 27017:27017 \
-v mongodb-data:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secretpassword \
mongo:7
Grundlegende CRUD-Operationen
Verbindung zu MongoDB über die Shell herstellen:
# Lokale MongoDB-Instanz verbinden
mongosh
# Remote-Server mit Authentifizierung verbinden
mongosh "mongodb://admin:password@192.168.1.100:27017/admin"
Create — Dokumente einfügen
// Zu einer Datenbank wechseln (oder sie anlegen)
use myapp
// Ein einzelnes Dokument einfügen
db.users.insertOne({
name: "Alice Johnson",
email: "alice@example.com",
role: "admin",
skills: ["python", "docker", "kubernetes"],
created: new Date()
})
// Mehrere Dokumente einfügen
db.users.insertMany([
{ name: "Bob Smith", email: "bob@example.com", role: "developer", skills: ["javascript", "react"] },
{ name: "Carol Lee", email: "carol@example.com", role: "devops", skills: ["terraform", "aws", "docker"] }
])
MongoDB legt Datenbank und Collection beim ersten Einfügen automatisch an — kein CREATE TABLE oder CREATE DATABASE nötig.
Read — Dokumente abfragen
// Alle Dokumente einer Collection abrufen
db.users.find()
// Mit einem Filter suchen
db.users.find({ role: "admin" })
// Verschachtelte Felder und Arrays abfragen
db.users.find({ skills: "docker" }) // Array enthält "docker"
db.users.find({ "skills.0": "python" }) // Erstes Skill ist "python"
// Vergleichsoperatoren
db.users.find({ age: { $gt: 25 } }) // Größer als
db.users.find({ role: { $in: ["admin", "devops"] } }) // Im Array enthalten
// Projektion — bestimmte Felder auswählen
db.users.find({ role: "admin" }, { name: 1, email: 1, _id: 0 })
// Sortieren und begrenzen
db.users.find().sort({ created: -1 }).limit(10)
// Dokumente zählen
db.users.countDocuments({ role: "developer" })
Update — Dokumente ändern
// Ein Dokument aktualisieren
db.users.updateOne(
{ email: "alice@example.com" },
{ $set: { role: "superadmin", lastLogin: new Date() } }
)
// Einem Array ein Element hinzufügen
db.users.updateOne(
{ email: "bob@example.com" },
{ $push: { skills: "typescript" } }
)
// Mehrere Dokumente aktualisieren
db.users.updateMany(
{ role: "developer" },
{ $set: { department: "engineering" } }
)
// Upsert — aktualisieren wenn vorhanden, einfügen wenn nicht
db.users.updateOne(
{ email: "dave@example.com" },
{ $set: { name: "Dave Wilson", role: "intern" } },
{ upsert: true }
)
Delete — Dokumente löschen
// Ein Dokument löschen
db.users.deleteOne({ email: "dave@example.com" })
// Mehrere Dokumente löschen
db.users.deleteMany({ role: "intern" })
// Gesamte Collection löschen
db.users.drop()
Indizierung für bessere Performance
Ohne Indizes führt MongoDB einen Collection-Scan durch — dabei wird jedes Dokument gelesen, um Treffer zu finden. Bei einer Collection mit Millionen von Dokumenten dauert das Sekunden statt Millisekunden.
// Einfeldindex anlegen
db.users.createIndex({ email: 1 }) // Aufsteigend
// Verbundindex anlegen (mehrere Felder)
db.users.createIndex({ role: 1, created: -1 })
// Eindeutigen Index anlegen (erzwingt Einzigartigkeit)
db.users.createIndex({ email: 1 }, { unique: true })
// Textindex für Volltextsuche
db.articles.createIndex({ title: "text", body: "text" })
db.articles.find({ $text: { $search: "mongodb tutorial" } })
// Alle Indizes einer Collection auflisten
db.users.getIndexes()
// Abfrage mit explain analysieren, ob ein Index genutzt wird
db.users.find({ email: "alice@example.com" }).explain("executionStats")
Faustregeln für Indizierung:
- Felder indizieren, die in
find()-Filtern,sort()und$matchin Aggregationen vorkommen - Bei Verbundindizes die Felder von der selektivsten zur am wenigsten selektiven Reihenfolge sortieren
- Felder mit geringer Kardinalität nicht indizieren (z. B. Boolean-Felder mit nur
true/false) - Jeder Index belegt RAM — mit
db.stats()unddb.collection.stats()überwachen
MongoDB im Vergleich mit anderen Datenbanken
| Merkmal | MongoDB | PostgreSQL | MySQL | Redis |
|---|---|---|---|---|
| Datenmodell | Dokumente (JSON) | Relational (Tabellen) | Relational (Tabellen) | Key-Value / Datenstrukturen |
| Schema | Flexibel (schemalos) | Strikt (SQL DDL) | Strikt (SQL DDL) | Schemalos |
| Abfragesprache | MQL + Aggregation | SQL | SQL | Befehle |
| Joins | $lookup (begrenzt) | Vollständige SQL-Joins | Vollständige SQL-Joins | Keine |
| Transaktionen | Multi-Dokument-ACID | Vollständig ACID | Vollständig ACID | Atomare Einzeloperationen |
| Skalierung | Horizontal (Sharding) | Vertikal (+ Read-Replicas) | Vertikal (+ Read-Replicas) | In-Memory, horizontal |
| Am besten für | Flexible Schemas, schnelle Entwicklung | Komplexe Abfragen, Datenintegrität | Webanwendungen, WordPress | Caching, Sessions, Echtzeit |
Aggregations-Pipeline
Die Aggregations-Pipeline ist MongoDBs Antwort auf komplexe SQL-Abfragen mit GROUP BY, JOIN und Unterabfragen:
// Benutzer nach Rolle zählen
db.users.aggregate([
{ $group: { _id: "$role", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
// Häufigste Skills über alle Benutzer ermitteln
db.users.aggregate([
{ $unwind: "$skills" },
{ $group: { _id: "$skills", count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 10 }
])
// Benutzer mit ihren Bestellungen verknüpfen (wie SQL JOIN)
db.orders.aggregate([
{ $lookup: {
from: "users",
localField: "userId",
foreignField: "_id",
as: "user"
}},
{ $unwind: "$user" },
{ $project: { orderTotal: 1, "user.name": 1, "user.email": 1 } }
])
Backup und Wiederherstellung
# Eine bestimmte Datenbank sichern
mongodump --db myapp --out /backup/$(date +%Y-%m-%d)
# Backup mit Authentifizierung
mongodump --uri="mongodb://admin:password@localhost:27017" --db myapp --out /backup/
# Alle Datenbanken sichern
mongodump --out /backup/full-$(date +%Y-%m-%d)
# Eine Datenbank wiederherstellen
mongorestore --db myapp /backup/2025-12-13/myapp
# Wiederherstellen und vorhandene Daten zuerst löschen
mongorestore --drop --db myapp /backup/2025-12-13/myapp
Fallstricke und Sonderfälle
Dokumentgrößenlimit: Ein einzelnes MongoDB-Dokument darf 16 MB nicht überschreiten. Für größere Dateien ist GridFS vorgesehen — MongoDBs Spezifikation zur Speicherung von Dateien über 16 MB auf mehrere Dokumente verteilt.
Keine Joins per Standard: Obwohl $lookup grundlegende Join-Funktionalität bietet, ist es langsamer als relationale Joins. Das Dokumentschema sollte so entworfen werden, dass zusammengehörige Daten innerhalb eines Dokuments eingebettet werden (Denormalisierung).
Write Concern und Datenverlust: Standardmäßig bestätigt MongoDB Schreibvorgänge, sobald sie den Primary erreicht haben. Stürzt der Primary vor der Replikation ab, gehen Daten verloren. Für kritische Daten writeConcern: { w: "majority" } verwenden, um auf die Replikation zu warten.
ObjectId ist nicht sequenziell: MongoDBs Standard-_id-Feld verwendet ObjectId, das zwar einen Zeitstempel kodiert, aber nicht streng sequenziell ist. Die _id-Reihenfolge nicht als Ersatz für ein created-Zeitstempelfeld verwenden.
Speicherverwaltung: MongoDBs WiredTiger-Engine nutzt verfügbaren RAM als Cache. Ein MongoDB-Server mit 8 GB RAM und einer 100-GB-Datenbank cached nur den aktiv genutzten Arbeitsbereich. Cache-Trefferquoten mit db.serverStatus().wiredTiger.cache überwachen.
Fehlerbehebung
MongoDB startet nicht
# Log auf Fehler prüfen
sudo journalctl -u mongod --no-pager -n 50
# Häufige Ursachen: zu wenig Speicherplatz oder falsche Berechtigungen
ls -la /var/lib/mongodb/
sudo chown -R mongodb:mongodb /var/lib/mongodb
Abfragen sind langsam
// Mit explain prüfen, ob Abfragen Indizes nutzen
db.users.find({ email: "alice@example.com" }).explain("executionStats")
// "COLLSCAN" in der Ausgabe bedeutet: kein Index wird verwendet
// Index auf dem abgefragten Feld erstellen
db.users.createIndex({ email: 1 })
Verbindung von Remote-Clients wird abgelehnt
# MongoDB bindet standardmäßig nur an localhost
# /etc/mongod.conf anpassen, um Remote-Verbindungen zu erlauben
# net:
# bindIp: 0.0.0.0 # Auf allen Interfaces lauschen
# WICHTIG: Zuerst Authentifizierung aktivieren!
sudo systemctl restart mongod
Zusammenfassung
- MongoDB speichert JSON-ähnliche Dokumente in Collections ohne vorher definiertes Schema — jedes Dokument kann andere Felder haben, ideal für sich ändernde Datenstrukturen
- CRUD-Operationen nutzen intuitive Methoden wie
insertOne,find,updateOneunddeleteOnemit JSON-Abfragefiltern statt SQL - Indizes sind entscheidend für die Performance — Indizes auf in Abfragen und Sortieroperationen verwendeten Feldern anlegen und mit
explain()die Indexnutzung prüfen - Die Aggregations-Pipeline übernimmt komplexe Datentransformationen, Gruppierungen und Joins, die in SQL GROUP BY und JOIN erfordern würden
- Regelmäßige Backups mit
mongodumperstellen und Wiederherstellungen mitmongorestoretesten — ein nicht getestetes Backup ist kein Backup - Zusammengehörige Daten im Dokument einbetten statt über Collections zu normalisieren — das reduziert den Bedarf an aufwendigen
$lookup-Joins