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(), dans sort() et dans $match des 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() et db.collection.stats()

Comparaison de MongoDB avec d’autres bases de données

FonctionnalitéMongoDBPostgreSQLMySQLRedis
Modèle de donnéesDocuments (JSON)Relationnel (tables)Relationnel (tables)Clé-valeur / structures de données
SchémaFlexible (schema-less)Strict (SQL DDL)Strict (SQL DDL)Schema-less
Langage de requêteMQL + AgrégationSQLSQLCommandes
Jointures$lookup (limité)Jointures SQL complètesJointures SQL complètesAucune
TransactionsACID multi-documentsACID completACID completAtomique mono-opération
ScalabilitéHorizontale (sharding)Verticale (+ read replicas)Verticale (+ read replicas)En mémoire, horizontale
Idéal pourSchémas flexibles, développement rapideRequêtes complexes, intégrité des donnéesApplications web, WordPressCache, 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, updateOne et deleteOne avec 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 mongodump et testez vos restaurations avec mongorestore — 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 $lookup coûteuses

Articles Connexes