MongoDB est une base de données NoSQL orientée documents qui stocke les données sous forme de documents JSON flexibles, plutôt que sous forme de lignes et de colonnes. Là où les bases relationnelles exigent de définir un schéma à l’avance et de restructurer les tables à chaque évolution, MongoDB permet à chaque document d’une collection d’avoir des champs différents — idéal pour les applications dont la structure de données évolue rapidement. Ce guide couvre l’installation de MongoDB, les opérations CRUD essentielles, les stratégies d’indexation et la configuration d’un replica set pour les déploiements en production.
Prérequis
- Un serveur Linux (Ubuntu 22.04 ou RHEL 8+ recommandé) avec au moins 2 Go de RAM
- Accès root ou sudo pour l’installation
- Compréhension de base du format de données JSON
- Familiarité avec les outils en ligne de commande
Installation de MongoDB
Ubuntu/Debian
# Import the MongoDB GPG key
curl -fsSL https://www.mongodb.org/static/pgp/server-7.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-7.0.gpg --dearmor
# Add the repository
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
# Install MongoDB
sudo apt update
sudo apt install -y mongodb-org
# Start and enable the service
sudo systemctl start mongod
sudo systemctl enable mongod
# Verify it is running
sudo systemctl status mongod
mongosh --eval "db.version()"
RHEL/CentOS
# Create the repository file
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
Opérations CRUD essentielles
Connectez-vous à MongoDB via le shell :
# Connect to local MongoDB
mongosh
# Connect to a remote server with authentication
mongosh "mongodb://admin:password@192.168.1.100:27017/admin"
Create — Insertion de documents
// Switch to (or create) a database
use myapp
// Insert a single document
db.users.insertOne({
name: "Alice Johnson",
email: "alice@example.com",
role: "admin",
skills: ["python", "docker", "kubernetes"],
created: new Date()
})
// Insert multiple documents
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 crée la base de données et la collection automatiquement au premier insert — aucun CREATE TABLE ni CREATE DATABASE requis.
Read — Interrogation de documents
// Find all documents in a collection
db.users.find()
// Find with a filter
db.users.find({ role: "admin" })
// Query nested fields and arrays
db.users.find({ skills: "docker" }) // Array contains "docker"
db.users.find({ "skills.0": "python" }) // First skill is "python"
// Comparison operators
db.users.find({ age: { $gt: 25 } }) // Greater than
db.users.find({ role: { $in: ["admin", "devops"] } }) // In array
// Projection — select specific fields
db.users.find({ role: "admin" }, { name: 1, email: 1, _id: 0 })
// Sort and limit
db.users.find().sort({ created: -1 }).limit(10)
// Count documents
db.users.countDocuments({ role: "developer" })
Update — Modification de documents
// Update one document
db.users.updateOne(
{ email: "alice@example.com" },
{ $set: { role: "superadmin", lastLogin: new Date() } }
)
// Add to an array
db.users.updateOne(
{ email: "bob@example.com" },
{ $push: { skills: "typescript" } }
)
// Update multiple documents
db.users.updateMany(
{ role: "developer" },
{ $set: { department: "engineering" } }
)
// Upsert — update if exists, insert if not
db.users.updateOne(
{ email: "dave@example.com" },
{ $set: { name: "Dave Wilson", role: "intern" } },
{ upsert: true }
)
Delete — Suppression de documents
// Delete one document
db.users.deleteOne({ email: "dave@example.com" })
// Delete multiple documents
db.users.deleteMany({ role: "intern" })
// Drop an entire collection
db.users.drop()
Indexation et performances
Sans index, MongoDB effectue un parcours complet de collection — lisant chaque document pour trouver les correspondances. Sur une collection de plusieurs millions de documents, cela prend des secondes au lieu de millisecondes.
// Create a single-field index
db.users.createIndex({ email: 1 }) // Ascending
// Create a compound index (multiple fields)
db.users.createIndex({ role: 1, created: -1 })
// Create a unique index (enforces uniqueness)
db.users.createIndex({ email: 1 }, { unique: true })
// Create a text index for full-text search
db.articles.createIndex({ title: "text", body: "text" })
db.articles.find({ $text: { $search: "mongodb tutorial" } })
// List all indexes on a collection
db.users.getIndexes()
// Explain a query to see if it uses an index
db.users.find({ email: "alice@example.com" }).explain("executionStats")
Règles pratiques pour l’indexation :
- Indexez les champs utilisés dans les filtres de
find(), danssort()et dans$matchdes agrégations - Dans les index composés, ordonnez les champs du plus sélectif au moins sélectif
- Évitez d’indexer les champs à faible cardinalité (ex. : champs booléens avec seulement
true/false) - Chaque index consomme de la RAM — surveillez avec
db.stats()etdb.collection.stats()
Comparaison de MongoDB avec d’autres bases de données
| Fonctionnalité | MongoDB | PostgreSQL | MySQL | Redis |
|---|---|---|---|---|
| Modèle de données | Documents (JSON) | Relationnel (tables) | Relationnel (tables) | Clé-valeur / structures de données |
| Schéma | Flexible (schema-less) | Strict (SQL DDL) | Strict (SQL DDL) | Schema-less |
| Langage de requête | MQL + Agrégation | SQL | SQL | Commandes |
| Jointures | $lookup (limité) | Jointures SQL complètes | Jointures SQL complètes | Aucune |
| Transactions | ACID multi-documents | ACID complet | ACID complet | Atomique mono-opération |
| Scalabilité | Horizontale (sharding) | Verticale (+ read replicas) | Verticale (+ read replicas) | En mémoire, horizontale |
| Idéal pour | Schémas flexibles, développement rapide | Requêtes complexes, intégrité des données | Applications web, WordPress | Cache, sessions, temps réel |
Pipeline d’agrégation
Le pipeline d’agrégation est la réponse de MongoDB aux requêtes SQL complexes avec GROUP BY, JOIN et sous-requêtes :
// Count users per role
db.users.aggregate([
{ $group: { _id: "$role", count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
// Find the most common skills across all users
db.users.aggregate([
{ $unwind: "$skills" },
{ $group: { _id: "$skills", count: { $sum: 1 } } },
{ $sort: { count: -1 } },
{ $limit: 10 }
])
// Join users with their orders (like 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 } }
])
Sauvegarde et restauration
# Backup a specific database
mongodump --db myapp --out /backup/$(date +%Y-%m-%d)
# Backup with authentication
mongodump --uri="mongodb://admin:password@localhost:27017" --db myapp --out /backup/
# Backup all databases
mongodump --out /backup/full-$(date +%Y-%m-%d)
# Restore a database
mongorestore --db myapp /backup/2025-12-13/myapp
# Restore dropping existing data first
mongorestore --drop --db myapp /backup/2025-12-13/myapp
Pièges et cas limites
Limite de taille d’un document : Un document MongoDB ne peut pas dépasser 16 Mo. Pour stocker des fichiers volumineux, utilisez GridFS — la spécification MongoDB pour stocker des fichiers de plus de 16 Mo sur plusieurs documents.
Pas de jointures par défaut : Bien que $lookup offre des fonctionnalités de jointure de base, il est plus lent que les jointures relationnelles. Concevez votre schéma documentaire pour intégrer les données liées dans un même document lorsque c’est possible (dénormalisation).
Write concern et perte de données : Par défaut, MongoDB acquitte les écritures après qu’elles atteignent le primaire. Si le primaire tombe avant la réplication, les données sont perdues. Pour les données critiques, utilisez writeConcern: { w: "majority" } pour attendre la réplication.
ObjectId non séquentiel : Le champ _id par défaut de MongoDB utilise ObjectId, qui encode un horodatage mais n’est pas strictement séquentiel. N’utilisez pas l’ordre des _id comme substitut à un champ timestamp created.
Stockage mappé en mémoire : Le moteur WiredTiger de MongoDB utilise la RAM disponible pour le cache. Un serveur MongoDB avec 8 Go de RAM et une base de 100 Go ne met en cache que l’ensemble de travail actif. Surveillez les taux de succès du cache avec db.serverStatus().wiredTiger.cache.
Résolution de Problèmes
MongoDB ne démarre pas
# Check the log for errors
sudo journalctl -u mongod --no-pager -n 50
# Common cause: insufficient disk space or wrong permissions
ls -la /var/lib/mongodb/
sudo chown -R mongodb:mongodb /var/lib/mongodb
Les requêtes sont lentes
// Use explain to check if queries use indexes
db.users.find({ email: "alice@example.com" }).explain("executionStats")
// Look for "COLLSCAN" in the output — it means no index is used
// Create an index on the queried field
db.users.createIndex({ email: 1 })
Connexion refusée depuis des clients distants
# MongoDB binds to localhost by default
# Edit /etc/mongod.conf to allow remote connections
# net:
# bindIp: 0.0.0.0 # Listen on all interfaces
# IMPORTANT: Enable authentication first!
sudo systemctl restart mongod
Résumé
- MongoDB stocke des documents JSON dans des collections sans schéma prédéfini — chaque document peut avoir des champs différents, ce qui le rend idéal pour les structures de données évolutives
- Les opérations CRUD utilisent des méthodes intuitives comme
insertOne,find,updateOneetdeleteOneavec des filtres JSON plutôt que du SQL - Les index sont essentiels pour les performances — créez-en sur les champs utilisés dans les requêtes et les tris, et utilisez
explain()pour vérifier leur utilisation - Le pipeline d’agrégation gère les transformations de données complexes, les regroupements et les jointures qui nécessiteraient GROUP BY et JOIN en SQL
- Sauvegardez régulièrement avec
mongodumpet testez vos restaurations avecmongorestore— une sauvegarde non testée n’est pas une vraie sauvegarde - Concevez vos documents pour intégrer les données liées plutôt que de normaliser sur plusieurs collections — cela réduit le besoin de jointures
$lookupcoûteuses