Eine Discord-Bot-MongoDB-Verbindung einzurichten ist einer der praktischsten Wege, deinem Bot ein dauerhaftes Gedächtnis zu geben, damit Daten nicht bei jedem Neustart des Prozesses verschwinden. Levelsysteme, Economy-Bots, Verwarnungs-Logs, Benutzereinstellungen — all das muss irgendwo gespeichert werden. Eine einfache JSON-Datei reicht für winzige Bots, scheitert aber, sobald du gleichzeitige Schreibvorgänge, Skalierung oder echte Abfragen brauchst. In dieser Anleitung verbinden wir MongoDB über Mongoose mit einem discord.js-Bot und speichern Benutzerdaten Schritt für Schritt richtig.
Warum MongoDB und Mongoose?
MongoDB ist eine NoSQL-Datenbank, die Daten als Dokumente in einer JSON-ähnlichen Struktur speichert. Für Discord-Bots passt das natürlich: Die Daten eines Nutzers bestehen ohnehin aus verschachtelten Feldern (Guthaben, Inventar, Einstellungen), und es ist einfacher, mit flexiblen Dokumenten zu arbeiten, als alles in ein starres Tabellenschema zu zwingen. Mongoose ist eine ODM-Bibliothek (Object Data Modeling) für MongoDB; sie setzt auf den rohen Treiber auf und ergänzt Schemavalidierung, Typprüfung und eine lesbare API.
- SQLite ist ideal für kleine, dateibasierte Bots auf einem einzelnen Server.
- MongoDB skaliert komfortabler für Bots, die über mehrere Server laufen, Sharding benötigen oder in der Cloud (MongoDB Atlas) liegen.
- Dank seines Schemas fängt Mongoose Fehler wie „ein Feld wurde mit dem falschen Typ geschrieben" ab, bevor sie in die Produktion gelangen.
Installation und der Connection String
Füge zuerst Mongoose zu deinem Projekt hinzu:
npm install mongoose
Als Nächstes brauchst du eine Datenbank. Der schnellste Weg ist MongoDB Atlas, das einen kostenlosen Tarif hat: Erstelle einen Cluster, lege einen Datenbankbenutzer an und kopiere den Connection String aus dem „Connect"-Bildschirm. Der String sieht so aus:
mongodb+srv://benutzer:passwort@cluster0.xxxxx.mongodb.net/botdb
Schreibe diesen String niemals fest in den Quellcode. Bewahre Geheimnisse wie Tokens und URIs in einer .env-Datei auf und füge sie zu .gitignore hinzu:
# .env
DISCORD_TOKEN=...
MONGO_URI=mongodb+srv://benutzer:passwort@cluster0.xxxxx.mongodb.net/botdb
MongoDB mit dem Bot verbinden
Öffne die Verbindung einmal beim Start, bevor der Bot bereit ist. Da das Verbinden asynchron ist, ist es wichtig, es mit await abzuwarten und Fehler abzufangen; andernfalls stürzt der Bot stillschweigend ab, wenn die Datenbank nicht erreichbar ist:
require('dotenv').config();
const mongoose = require('mongoose');
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers],
});
async function start() {
try {
await mongoose.connect(process.env.MONGO_URI);
console.log('Mit MongoDB verbunden');
} catch (err) {
console.error('MongoDB-Verbindungsfehler:', err);
process.exit(1);
}
await client.login(process.env.DISCORD_TOKEN);
}
start();
Ab Mongoose 6 sind alte Optionen wie useNewUrlParser Standard, daher ist keine zusätzliche Konfiguration nötig. Mongoose verwaltet den Connection Pool selbst; versuche nicht, dich bei jedem Befehl neu zu verbinden.
Ein Schema und Model definieren
In Mongoose werden Daten durch ein Schema beschrieben, und aus diesem Schema wird ein Model erstellt. Ein typisches Benutzer-Model in einer eigenen Datei zu halten ist der sauberste Ansatz:
// models/User.js
const { Schema, model } = require('mongoose');
const userSchema = new Schema({
userId: { type: String, required: true, unique: true },
guildId: { type: String, required: true },
balance: { type: Number, default: 0 },
xp: { type: Number, default: 0 },
level: { type: Number, default: 1 },
}, { timestamps: true });
module.exports = model('User', userSchema);
unique: true stellt sicher, dass es pro Nutzer nur ein Dokument gibt, und erstellt zugleich einen Index, was Abfragen beschleunigt. timestamps: true fügt automatisch die Felder createdAt und updatedAt hinzu.
Daten lesen und schreiben: das Upsert-Muster
Deine häufigste Operation ist „hole das Dokument dieses Nutzers, falls es existiert, andernfalls erstelle es". Dies mit einem einzigen Upsert statt mit zwei getrennten Abfragen zu lösen ist schneller und sicherer gegen gleichzeitige Aufrufe. findOneAndUpdate mit der Option upsert: true tut genau das:
const User = require('./models/User');
async function getUser(userId, guildId) {
return User.findOneAndUpdate(
{ userId, guildId },
{ $setOnInsert: { userId, guildId } },
{ upsert: true, new: true }
);
}
$setOnInsert läuft nur, wenn das Dokument erstmals erstellt wird; es überschreibt kein bestehendes Dokument. new: true gibt das aktualisierte (oder neu erstellte) Dokument zurück. Wenn du einen Wert erhöhen willst, nutze den $inc-Operator, statt das Dokument zu laden und von Hand zu ändern; das ist atomar und verhindert Race Conditions:
// In einem Slash-Befehl: dem Nutzer Guthaben gutschreiben
await User.updateOne(
{ userId: interaction.user.id, guildId: interaction.guildId },
{ $inc: { balance: 100 } },
{ upsert: true }
);
Ein vollständiger Guthaben-Befehl sieht so aus:
if (interaction.commandName === 'balance') {
const doc = await getUser(interaction.user.id, interaction.guildId);
await interaction.reply(`Dein Guthaben: ${doc.balance} 💰`);
}
Performance- und Produktionstipps
Wenn dein Bot wächst, machen ein paar Gewohnheiten den Unterschied:
- Indizes hinzufügen: Gib oft abgefragten Feldern (etwa
xpfür eine Bestenliste) im Schemaindex: true. Abfragen ohne Index durchsuchen die gesamte Collection. - Nutze
.lean()für reine Leseabfragen:User.find().sort({ xp: -1 }).limit(10).lean()liefert einfache JavaScript-Objekte statt vollständiger Mongoose-Dokumente und ist spürbar schneller. - Höre auf Verbindungsereignisse: Logge Verbindungsabbrüche mit
mongoose.connection.on('error', ...); stille Fehler sind am schwersten aufzuspüren. - IP-Zugriff einschränken: Erlaube in Atlas unter Network Access nur die IP deines Bot-Servers — verwende nicht
0.0.0.0/0.
Häufige Fragen
Sollte ich MongoDB oder SQLite wählen?
Für einen kleinen/mittleren Bot auf einem einzelnen VPS reicht SQLite meist aus und ist einfacher einzurichten. Wenn deine Daten wachsen, du Sharding in Betracht ziehst oder eine verwaltete Cloud-Datenbank willst, skaliert MongoDB komfortabler. Wähle nach Bedarf; beide sind passende Werkzeuge für dauerhafte Speicherung.
Muss ich mich bei jedem Befehl neu verbinden?
Nein. mongoose.connect wird einmal aufgerufen, beim Start des Bots. Mongoose verwaltet den Connection Pool, und deine Models teilen sich diese eine Verbindung. Sich bei jedem Befehl neu zu verbinden verursacht ernste Performance-Probleme.
Kann ich das Schema später ändern?
Ja. Da MongoDB flexibel ist, bricht das Hinzufügen eines neuen Feldes bestehende Dokumente nicht; für Dokumente, denen das Feld fehlt, greift der default-Wert aus dem Schema. Für größere Umwandlungen wie Typänderungen ist es jedoch besser, ein Migrationsskript zu schreiben.
Möchtest du einen Discord-Bot, der seine Daten sicher speichert? Ich baue MongoDB-gestützte Economy-, Level- und Moderationssysteme. Lass uns dein Projekt gemeinsam umsetzen — kontaktiere mich.