MongoDB ist eine dokumentenorientierte NoSQL-Datenbank. Sie speichert Daten in flexiblen JSON-ähnlichen Dokumenten statt in starren Tabellen.

Vorteile von MongoDB

NoSQL vs. SQL

| Feature | MongoDB | SQL | |---------|---------|-----| | Schema | Flexibel | Starr | | Datenformat | JSON/BSON | Tabellen | | Skalierung | Horizontal | Vertikal | | Joins | Embedded/Lookup | Native | | Transaktionen | Seit 4.0 | Native |

Anwendungsfälle

- Content Management Systeme
- Echtzeit-Analytik
- IoT-Daten
- Kataloge und Inventar
- Mobile Apps
- Gaming (Leaderboards, Sessions)

Installation

Debian/Ubuntu

# GPG-Key
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | gpg --dearmor -o /usr/share/keyrings/mongodb.gpg

# Repository
echo "deb [signed-by=/usr/share/keyrings/mongodb.gpg] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/7.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-7.0.list

# Installieren
apt update
apt install mongodb-org

# Starten
systemctl enable --now 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=password \
  mongo:7

Konfiguration

mongod.conf

# /etc/mongod.conf

storage:
  dbPath: /var/lib/mongodb
  journal:
    enabled: true

systemLog:
  destination: file
  logAppend: true
  path: /var/log/mongodb/mongod.log

net:
  port: 27017
  bindIp: 127.0.0.1

security:
  authorization: enabled

Authentifizierung aktivieren

# Erst Admin-User erstellen (ohne Auth)
mongosh

use admin
db.createUser({
  user: "admin",
  pwd: "securePassword",
  roles: ["root"]
})

# Dann in mongod.conf:
# security:
#   authorization: enabled

# Service neustarten
systemctl restart mongod

MongoDB Shell (mongosh)

Verbinden

# Lokal
mongosh

# Mit Authentifizierung
mongosh -u admin -p password --authenticationDatabase admin

# Remote
mongosh "mongodb://user:password@hostname:27017/database"

Grundbefehle

// Datenbanken anzeigen
show dbs

// Datenbank wechseln/erstellen
use mydb

// Collections anzeigen
show collections

// Hilfe
help
db.help()

CRUD-Operationen

Dokument einfügen

// Ein Dokument
db.users.insertOne({
  name: "Max Mustermann",
  email: "max@example.com",
  age: 30,
  tags: ["admin", "developer"],
  address: {
    city: "Berlin",
    zip: "10115"
  },
  createdAt: new Date()
})

// Mehrere Dokumente
db.users.insertMany([
  { name: "Anna", email: "anna@example.com", age: 25 },
  { name: "Tom", email: "tom@example.com", age: 35 }
])

Dokumente abfragen

// Alle
db.users.find()

// Mit Filter
db.users.find({ name: "Max Mustermann" })

// Vergleichsoperatoren
db.users.find({ age: { $gt: 25 } })        // Größer als
db.users.find({ age: { $gte: 25 } })       // Größer oder gleich
db.users.find({ age: { $lt: 30 } })        // Kleiner als
db.users.find({ age: { $ne: 25 } })        // Ungleich
db.users.find({ age: { $in: [25, 30] } })  // In Array

// Logische Operatoren
db.users.find({ $and: [{ age: { $gt: 20 } }, { age: { $lt: 30 } }] })
db.users.find({ $or: [{ name: "Max" }, { name: "Anna" }] })

// Nested Documents
db.users.find({ "address.city": "Berlin" })

// Array enthält
db.users.find({ tags: "admin" })

// Projektion (Felder auswählen)
db.users.find({}, { name: 1, email: 1, _id: 0 })

// Sortieren und Limitieren
db.users.find().sort({ age: -1 }).limit(10)

Dokumente aktualisieren

// Ein Dokument
db.users.updateOne(
  { name: "Max Mustermann" },
  { $set: { age: 31 } }
)

// Mehrere Dokumente
db.users.updateMany(
  { age: { $lt: 30 } },
  { $set: { status: "young" } }
)

// Upsert (Insert wenn nicht existiert)
db.users.updateOne(
  { email: "new@example.com" },
  { $set: { name: "New User" } },
  { upsert: true }
)

// Operatoren
db.users.updateOne(
  { name: "Max" },
  {
    $set: { status: "active" },      // Feld setzen
    $unset: { temporary: "" },       // Feld entfernen
    $inc: { loginCount: 1 },         // Inkrementieren
    $push: { tags: "verified" },     // Array erweitern
    $pull: { tags: "temporary" }     // Aus Array entfernen
  }
)

Dokumente löschen

// Ein Dokument
db.users.deleteOne({ name: "Test" })

// Mehrere Dokumente
db.users.deleteMany({ status: "inactive" })

// Alle Dokumente
db.users.deleteMany({})

// Collection löschen
db.users.drop()

Indizes

Index erstellen

// Einfacher Index
db.users.createIndex({ email: 1 })

// Zusammengesetzter Index
db.users.createIndex({ name: 1, age: -1 })

// Unique Index
db.users.createIndex({ email: 1 }, { unique: true })

// Text Index (Volltextsuche)
db.articles.createIndex({ title: "text", content: "text" })

// TTL Index (automatisches Löschen)
db.sessions.createIndex({ createdAt: 1 }, { expireAfterSeconds: 3600 })

Indizes verwalten

// Indizes anzeigen
db.users.getIndexes()

// Index löschen
db.users.dropIndex("email_1")

// Alle Indizes löschen (außer _id)
db.users.dropIndexes()

Query analysieren

// Execution Plan
db.users.find({ email: "max@example.com" }).explain("executionStats")

Aggregation Pipeline

Grundstruktur

db.orders.aggregate([
  { $match: { status: "completed" } },
  { $group: { _id: "$customerId", total: { $sum: "$amount" } } },
  { $sort: { total: -1 } },
  { $limit: 10 }
])

Wichtige Stages

// $match - Filtern
{ $match: { status: "active" } }

// $group - Gruppieren
{ $group: {
    _id: "$category",
    count: { $sum: 1 },
    avgPrice: { $avg: "$price" },
    totalRevenue: { $sum: "$revenue" }
}}

// $sort - Sortieren
{ $sort: { count: -1 } }

// $limit / $skip - Pagination
{ $skip: 20 }
{ $limit: 10 }

// $project - Felder auswählen/transformieren
{ $project: {
    name: 1,
    fullName: { $concat: ["$firstName", " ", "$lastName"] },
    year: { $year: "$createdAt" }
}}

// $lookup - Join
{ $lookup: {
    from: "orders",
    localField: "_id",
    foreignField: "customerId",
    as: "orders"
}}

// $unwind - Array auflösen
{ $unwind: "$tags" }

Praktisches Beispiel

// Umsatz pro Monat
db.orders.aggregate([
  { $match: {
      createdAt: { $gte: ISODate("2024-01-01") }
  }},
  { $group: {
      _id: { $month: "$createdAt" },
      revenue: { $sum: "$total" },
      orders: { $sum: 1 }
  }},
  { $sort: { _id: 1 } }
])

Replikation (Replica Set)

Replica Set initialisieren

// Auf Primary
rs.initiate({
  _id: "rs0",
  members: [
    { _id: 0, host: "mongo1:27017", priority: 2 },
    { _id: 1, host: "mongo2:27017", priority: 1 },
    { _id: 2, host: "mongo3:27017", priority: 1 }
  ]
})

Node-Konfiguration

# mongod.conf
replication:
  replSetName: "rs0"

Status prüfen

rs.status()
rs.conf()
rs.isMaster()

Sharding

Sharded Cluster

                    ┌─────────────┐
                    │   mongos    │  (Router)
                    └─────────────┘
                           │
         ┌─────────────────┼─────────────────┐
         ▼                 ▼                 ▼
   ┌──────────┐      ┌──────────┐      ┌──────────┐
   │ Shard 1  │      │ Shard 2  │      │ Shard 3  │
   │ (RS)     │      │ (RS)     │      │ (RS)     │
   └──────────┘      └──────────┘      └──────────┘
         │                 │                 │
         └─────────────────┼─────────────────┘
                           ▼
                    ┌─────────────┐
                    │ Config RS   │
                    └─────────────┘

Sharding aktivieren

// Datenbank für Sharding aktivieren
sh.enableSharding("mydb")

// Collection sharden
sh.shardCollection("mydb.users", { region: 1 })

// Status
sh.status()

Backup und Restore

mongodump / mongorestore

# Alle Datenbanken
mongodump --out /backup/$(date +%Y%m%d)

# Eine Datenbank
mongodump --db mydb --out /backup/

# Mit Authentifizierung
mongodump -u admin -p password --authenticationDatabase admin --db mydb

# Restore
mongorestore /backup/mydb/
mongorestore --db mydb /backup/mydb/

Einzelne Collection

# Export als JSON
mongoexport --db mydb --collection users --out users.json

# Import
mongoimport --db mydb --collection users --file users.json

Sicherheit

Benutzer erstellen

use mydb
db.createUser({
  user: "appuser",
  pwd: "password",
  roles: [
    { role: "readWrite", db: "mydb" }
  ]
})

Rollen

| Rolle | Berechtigung | |-------|--------------| | read | Nur lesen | | readWrite | Lesen und Schreiben | | dbAdmin | Index- und Schema-Management | | userAdmin | Benutzerverwaltung | | dbOwner | Vollzugriff auf Datenbank | | root | Vollzugriff auf alles |

Netzwerk-Sicherheit

# mongod.conf
net:
  bindIp: 127.0.0.1,192.168.1.10
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongodb.pem
    CAFile: /etc/ssl/ca.pem

Monitoring

Server-Status

db.serverStatus()
db.stats()
db.collection.stats()

Current Operations

db.currentOp()
db.killOp(opId)

Profiling

// Profiler aktivieren
db.setProfilingLevel(2)  // 0=off, 1=slow, 2=all

// Profiling-Daten
db.system.profile.find().sort({ ts: -1 }).limit(10)

Troubleshooting

Logs

tail -f /var/log/mongodb/mongod.log

Verbindungsprobleme

# Port prüfen
ss -tlnp | grep 27017

# Verbindung testen
mongosh --eval "db.adminCommand('ping')"

Performance

// Langsame Queries
db.setProfilingLevel(1, { slowms: 100 })

// Index-Nutzung prüfen
db.collection.find({...}).explain("executionStats")

Zusammenfassung

| Befehl | Funktion | |--------|----------| | find() | Dokumente suchen | | insertOne/Many() | Einfügen | | updateOne/Many() | Aktualisieren | | deleteOne/Many() | Löschen | | aggregate() | Aggregation Pipeline | | createIndex() | Index erstellen |

| Operator | Funktion | |----------|----------| | $gt, $lt, $gte, $lte | Vergleiche | | $in, $nin | In/Nicht in Array | | $and, $or, $not | Logisch | | $set, $unset | Felder setzen/entfernen | | $push, $pull | Array-Operationen | | $inc | Inkrementieren |

| Port | Dienst | |------|--------| | 27017 | MongoDB | | 27018 | Sharding (Shard) | | 27019 | Sharding (Config) |

Fazit

MongoDB bietet mit seinem flexiblen Dokumentenmodell große Vorteile für Anwendungen mit wechselnden Anforderungen. Die Aggregation Pipeline ermöglicht komplexe Datenanalysen. Für Skalierung stehen Replica Sets und Sharding zur Verfügung. Die JSON-ähnliche Syntax macht den Einstieg leicht. Für Transaktionen über mehrere Dokumente sind relationale Datenbanken oft besser geeignet, aber MongoDB deckt viele moderne Anwendungsfälle hervorragend ab.