aslain.dev
0%
01 Hizmetler 02 Hakkımda 03 Projeler 04 Stack 05 Blog 06 İletişim
← Tüm makaleler Bots Discord

Discord Bot MongoDB : stocker les données avec Mongoose

Mettre en place une connexion Discord bot MongoDB est l'un des moyens les plus pratiques de donner à votre bot une mémoire persistante, afin que les données ne disparaissent pas à chaque redémarrage du processus. Systèmes de niveaux, bots d'économie, journaux d'avertissements, paramètres utilisateur : tout cela doit être écrit quelque part. Un simple fichier JSON suffit pour de petits bots, mais il s'effondre dès que vous avez besoin d'écritures concurrentes, de montée en charge ou de vraies requêtes. Dans ce guide, nous connectons MongoDB à un bot discord.js via Mongoose et stockons correctement les données utilisateur, étape par étape.

Pourquoi MongoDB et Mongoose ?

MongoDB est une base de données NoSQL qui stocke les données sous forme de documents dans une structure proche du JSON. Pour les bots Discord, c'est un choix naturel : les données d'un utilisateur sont déjà composées de champs imbriqués (solde, inventaire, paramètres), et il est plus simple de travailler avec des documents flexibles que de tout forcer dans un schéma de table rigide. Mongoose est une bibliothèque ODM (Object Data Modeling) pour MongoDB ; elle s'appuie sur le pilote brut et ajoute la validation de schéma, la vérification de type et une API lisible.

  • SQLite est idéal pour de petits bots monoserveur basés sur un fichier.
  • MongoDB monte en charge plus confortablement pour les bots répartis sur plusieurs serveurs, nécessitant du sharding ou hébergés dans le cloud (MongoDB Atlas).
  • Grâce à son schéma, Mongoose détecte des erreurs du type « un champ a été écrit avec le mauvais type » avant qu'elles n'atteignent la production.

Installation et chaîne de connexion

Ajoutez d'abord Mongoose à votre projet :

npm install mongoose

Il vous faut ensuite une base de données. La voie la plus rapide est MongoDB Atlas, qui propose une offre gratuite : créez un cluster, définissez un utilisateur de base de données et copiez la chaîne de connexion depuis l'écran « Connect ». La chaîne ressemble à ceci :

mongodb+srv://utilisateur:motdepasse@cluster0.xxxxx.mongodb.net/botdb

N'écrivez jamais cette chaîne en dur dans le code. Conservez les secrets comme les tokens et les URI dans un fichier .env et ajoutez-le à .gitignore :

# .env
DISCORD_TOKEN=...
MONGO_URI=mongodb+srv://utilisateur:motdepasse@cluster0.xxxxx.mongodb.net/botdb

Connecter MongoDB au bot

Ouvrez la connexion une seule fois au démarrage, avant que le bot ne soit prêt. Comme la connexion est asynchrone, il est important de l'await et d'attraper les erreurs ; sinon, le bot plantera silencieusement si la base est inaccessible :

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('Connecté à MongoDB');
  } catch (err) {
    console.error('Erreur de connexion MongoDB :', err);
    process.exit(1);
  }
  await client.login(process.env.DISCORD_TOKEN);
}

start();

Depuis Mongoose 6, les anciennes options comme useNewUrlParser sont activées par défaut, aucune configuration supplémentaire n'est donc nécessaire. Mongoose gère lui-même le pool de connexions ; n'essayez pas de vous reconnecter à chaque commande.

Définir un schéma et un modèle

Dans Mongoose, les données sont décrites par un schéma, et un modèle est créé à partir de ce schéma. Garder un modèle utilisateur typique dans son propre fichier est l'approche la plus propre :

// 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 garantit qu'il n'existe qu'un seul document par utilisateur et crée également un index, ce qui accélère les requêtes. timestamps: true ajoute automatiquement les champs createdAt et updatedAt.

Lire et écrire des données : le motif upsert

Votre opération la plus fréquente est « récupérer le document de cet utilisateur s'il existe, le créer sinon ». Résoudre cela avec un seul upsert plutôt qu'avec deux requêtes distinctes est à la fois plus rapide et plus sûr face aux appels concurrents. findOneAndUpdate avec l'option upsert: true fait exactement cela :

const User = require('./models/User');

async function getUser(userId, guildId) {
  return User.findOneAndUpdate(
    { userId, guildId },
    { $setOnInsert: { userId, guildId } },
    { upsert: true, new: true }
  );
}

$setOnInsert ne s'exécute que lors de la première création du document ; il n'écrase pas un document existant. new: true renvoie le document mis à jour (ou nouvellement créé). Lorsque vous voulez incrémenter une valeur, utilisez l'opérateur $inc plutôt que de récupérer le document et de le modifier à la main ; c'est atomique et cela évite les conditions de course :

// Dans une commande slash : créditer du solde à l'utilisateur
await User.updateOne(
  { userId: interaction.user.id, guildId: interaction.guildId },
  { $inc: { balance: 100 } },
  { upsert: true }
);

Une commande de solde complète ressemble à ceci :

if (interaction.commandName === 'balance') {
  const doc = await getUser(interaction.user.id, interaction.guildId);
  await interaction.reply(`Ton solde : ${doc.balance} 💰`);
}

Performance et conseils pour la production

À mesure que votre bot grandit, quelques habitudes font la différence :

  • Ajoutez des index : donnez index: true dans le schéma aux champs souvent interrogés (comme xp pour un classement). Les requêtes sans index parcourent toute la collection.
  • Utilisez .lean() pour les requêtes en lecture seule : User.find().sort({ xp: -1 }).limit(10).lean() renvoie de simples objets JavaScript au lieu de documents Mongoose complets et est nettement plus rapide.
  • Écoutez les événements de connexion : journalisez les déconnexions avec mongoose.connection.on('error', ...) ; les échecs silencieux sont les plus difficiles à diagnostiquer.
  • Restreignez l'accès IP : dans Atlas, n'autorisez que l'IP du serveur de votre bot sous Network Access — n'utilisez pas 0.0.0.0/0.

Questions fréquentes

Dois-je choisir MongoDB ou SQLite ?

Pour un bot petit/moyen tournant sur un seul VPS, SQLite suffit généralement et est plus simple à configurer. À mesure que vos données grandissent, si vous envisagez le sharding ou si vous voulez une base cloud managée, MongoDB monte en charge plus confortablement. Choisissez selon le besoin ; les deux sont de bons outils de stockage persistant.

Dois-je me reconnecter à chaque commande ?

Non. mongoose.connect est appelé une seule fois, au démarrage du bot. Mongoose gère le pool de connexions et vos modèles partagent cette unique connexion. Se reconnecter à chaque commande provoque de graves problèmes de performance.

Puis-je modifier le schéma plus tard ?

Oui. MongoDB étant flexible, ajouter un nouveau champ ne casse pas les documents existants ; pour les documents qui en manquent, la valeur default du schéma prend le relais. Pour des transformations plus importantes comme un changement de type, il est toutefois préférable d'écrire un script de migration.

Vous voulez un bot Discord qui stocke ses données en toute sécurité ? Je développe des systèmes d'économie, de niveaux et de modération adossés à MongoDB. Donnons vie à votre projet ensemble — contactez-moi.

Devamı için