Cours MongoDB Complet 🍃

Les 12 chapitres essentiels — documents, requêtes, agrégation, index, Mongoose et Atlas

12
Chapitres
120+
Exemples
MongoDB 7+
Version
A1→C2
Niveaux

CHAPITRE 01

Introduction et installation

🍃 Premiers pas
// Installer MongoDB
// Docker (recommandé) :
docker run -d -p 27017:27017 –name mongo \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=secret mongo:7

// macOS : brew install mongodb-community
// Ubuntu : docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/
// Cloud gratuit : MongoDB Atlas → cloud.mongodb.com

// Se connecter
mongosh
mongosh « mongodb://admin:secret@localhost:27017 »

// Commandes mongosh
show dbs // Lister les bases
use mon_app // Créer/utiliser une base
show collections // Lister les collections
db.stats() // Statistiques

// Clients : MongoDB Compass (officiel), Studio 3T, NoSQLBooster

MongoDB est la BDD NoSQL orientée documents la plus populaire. Créée en 2009, elle stocke des documents JSON (BSON en interne) au lieu de lignes dans des tables. Pas de schéma rigide — chaque document peut avoir une structure différente. Utilisée par Google, eBay, Adobe, Forbes, EA Games, Toyota et Uber.

⚖️ SQL vs MongoDB — Vocabulaire
SQL (MySQL/PostgreSQL) MongoDB
Base de données Base de données
Table Collection
Ligne (row) Document (JSON/BSON)
Colonne Champ (field)
PRIMARY KEY _id (ObjectId auto-généré)
JOIN $lookup (ou embedding)
Schema fixe obligatoire Schema flexible

CHAPITRE 02

Documents et collections

📄 Structure d'un document
// Un document MongoDB = un objet JSON

// Types BSON : String, Number (int32/int64/double/decimal128),
// Boolean, Date, ObjectId, Array, Object, null, Binary, Regex

L'_id est obligatoire et unique. Si vous ne le spécifiez pas, MongoDB génère un ObjectId — 12 octets contenant un timestamp, une valeur aléatoire et un compteur. Vous pouvez aussi utiliser un string, un nombre ou un UUID.

CHAPITRE 03

Insérer des données

✏️ Créer des documents
// Insérer un document
db.users.insertOne()

// Insérer plusieurs documents
db.users.insertMany([
,
,

])

// La collection est créée automatiquement au premier insert
// Pas besoin de CREATE TABLE

CHAPITRE 04

Lire et filtrer (find)

🔍 Requêtes de lecture
// Tous les documents
db.users.find()

// Filtres
db.users.find()
db.users.find() // age > 25
db.users.find() // 18 ≤ age ≤ 30
db.users.find()
db.users.find() // ≠ admin

// Un seul document
db.users.findOne()

// Projection — choisir les champs
db.users.find(, )

// Tri, limite, pagination
db.users.find().sort() // Plus récents
db.users.find().limit(20) // 20 premiers
db.users.find().skip(40).limit(20) // Page 3
db.users.countDocuments()

// Dot notation (imbriqué + arrays)
db.users.find()
db.users.find() // Array contient
db.users.find()
db.users.find() // 3 éléments

CHAPITRE 05

Modifier et supprimer

🔧 Opérations d'écriture
// UPDATE un document
db.users.updateOne(
,

)

// UPDATE plusieurs
db.users.updateMany(
,

)

// Opérateurs de mise à jour
db.users.updateOne(, {
$set: { name: « Alice M. » },
$unset: { bio: «  » }, // Supprimer un champ
$inc: { loginCount: 1 }, // Incrémenter
$push: { tags: « react » }, // Ajouter à array
$pull: , // Retirer de array
$addToSet: { tags: « docker » }, // Ajouter si absent
$currentDate: { updatedAt: true }
})

// UPSERT — insérer si absent
db.users.updateOne(
,
,

)

// REPLACE — remplacer entièrement
db.users.replaceOne(
,

)

// DELETE
db.users.deleteOne()
db.users.deleteMany()
db.users.drop() // Vider la collection

Toujours $set dans updateOne/updateMany. Sans opérateur, MongoDB refuse la requête. Utilisez replaceOne pour remplacer entièrement un document.

CHAPITRE 06

Opérateurs avancés

🔧 Opérateurs de requête
Catégorie Opérateur SQL Exemple
Comparaison $gt / $gte > / ≥
$lt / $lte < / ≤
$in IN
$ne / $nin ≠ / NOT IN
Logique $or OR
$and / $not AND / NOT
Existence $exists IS (NOT) NULL
$type
Texte $regex LIKE
Array $elemMatch
// AND implicite (conditions sur le même niveau)
db.users.find()

CHAPITRE 07

Agrégation (pipeline)

📊 Pipeline d'agrégation
// Pipeline = chaîne d'étapes qui transforment les données

// Nombre de posts par auteur
db.posts.aggregate([
, // WHERE
,
, // ORDER BY DESC
// LIMIT
])

// Jointure ($lookup = LEFT JOIN)
db.posts.aggregate([
,
, // Array → objet

])

🔧 Étapes du pipeline
Étape SQL Description
$match WHERE Filtrer les documents
$group GROUP BY Regrouper + agréger ($sum, $avg, $min, $max)
$sort ORDER BY Trier (1 = ASC, -1 = DESC)
$limit / $skip LIMIT / OFFSET Pagination
$project SELECT Choisir/renommer les champs
$lookup LEFT JOIN Joindre une autre collection
$unwind Éclater un array en documents
$addFields AS Ajouter des champs calculés
$facet Plusieurs pipelines en parallèle

Le pipeline est le vrai pouvoir de MongoDB. Chaque étape transforme et passe au suivant (comme un pipe Unix). Mettez $match le plus tôt possible — ça réduit le volume traité et utilise les index.

CHAPITRE 08

Index et performance

⚡ Créer des index
// Index simple
db.users.createIndex() // 1=ASC, -1=DESC

// Index unique
db.users.createIndex(, )

// Index composé
db.posts.createIndex()

// Index partiel
db.posts.createIndex(
,

)

// Index texte (full-text search basique)
db.posts.createIndex()
db.posts.find()

// Index TTL — suppression automatique après N secondes
db.sessions.createIndex(, )

// Analyser une requête
db.users.find().explain(« executionStats »)
// « COLLSCAN » = full scan (lent) | « IXSCAN » = index (rapide)

// Voir / supprimer
db.users.getIndexes()
db.users.dropIndex(« email_1 »)

CHAPITRE 09

Modélisation des données

📐 Embedding vs Referencing
// 1. EMBEDDING — imbriquer dans le document
// ✅ Quand : 1-to-1 ou 1-to-few, données lues ensemble

// 2. REFERENCING — stocker un ID (comme une FK en SQL)
// ✅ Quand : 1-to-many, données modifiées indépendamment
// posts

// comments (1 post = beaucoup de comments)

Critère Embedding Referencing
Lecture 1 requête Nécessite $lookup
Écriture Peut dupliquer Pas de duplication
Taille doc ⚠️ Limite 16 Mo Pas de limite
Relation 1-to-1, 1-to-few 1-to-many, many-to-many
Exemple Adresse, tags Commentaires, commandes

Règle d'or : « les données lues ensemble vivent ensemble. » Si vous affichez toujours l'adresse avec l'utilisateur → embedding. Si les commentaires sont paginés séparément → referencing. Limite : 16 Mo par document.

CHAPITRE 10

Mongoose (Node.js)

🟢 ODM pour Node.js
// npm install mongoose
const mongoose = require('mongoose');
await mongoose.connect('mongodb://localhost:27017/mon_app');

// Schéma + Modèle
const userSchema = new mongoose.Schema(, ); // createdAt + updatedAt auto

const User = mongoose.model('User', userSchema);

// CRUD
const user = await User.create();
const users = await User.find().sort().limit(20);
const one = await User.findById(id);
await User.findByIdAndUpdate(id, , );
await User.findByIdAndDelete(id);

// Populate (joindre les références)
const posts = await Post.find().populate('userId', 'name email');
// → userId remplacé par de l'user

Mongoose ajoute schéma + validation au-dessus de MongoDB. timestamps: true gère createdAt/updatedAt. retourne le document après modification. populate() résout les références comme un JOIN côté application.

CHAPITRE 11

MongoDB Atlas (cloud)

☁️ MongoDB managé
// 1. Créer un compte sur cloud.mongodb.com
// 2. Créer un cluster (M0 = gratuit, 512 Mo)
// 3. Configurer Network Access (IP whitelist)
// 4. Créer un Database User
// 5. Récupérer la connection string

// Connexion Node.js
await mongoose.connect(
'mongodb+srv://user:pass@cluster0.xxxxx.mongodb.net/mon_app'
);

Fonctionnalité Atlas Description
M0 (gratuit) 512 Mo, parfait pour prototyper
Atlas Search Full-text search (basé sur Lucene)
Vector Search Recherche vectorielle IA (embeddings, RAG)
Charts Dashboards / visualisations intégrées
Backups auto Snapshots continus, restauration point-in-time
Monitoring Performance Advisor, alertes temps réel

CHAPITRE 12

Bonnes pratiques

⚖️ Quand MongoDB vs SQL
Critère MongoDB SQL (PostgreSQL/MySQL)
Schéma Flexible (change souvent) Fixe et structuré
Relations Peu de JOINs complexes Beaucoup de JOINs
Scaling Horizontal natif (sharding) Vertical (+ read replicas)
Transactions Supportées (coûteuses) ACID natif, très performant
Cas d'usage IoT, logs, CMS, temps réel, catalogues Finance, e-commerce, ERP

MongoDB n'est PAS un remplacement universel de SQL. Si vos données ont beaucoup de relations (users → orders → products → categories), utilisez PostgreSQL. MongoDB excelle quand les données sont naturellement des « documents » et quand le schéma évolue rapidement.

✅ Bonnes pratiques

✅ À FAIRE
• Index sur les champs filtrés/triés
• Embedding pour les données lues ensemble
• Mongoose (schéma + validation) en Node.js
$match en premier dans le pipeline
• Index unique sur email, slug
explain() sur les requêtes lentes
timestamps: true dans Mongoose
• Index TTL pour sessions/tokens
• Atlas pour la production
• Projections (champs utiles seulement)

❌ À ÉVITER
• MongoDB pour des données très relationnelles
• Documents > 16 Mo (embedding excessif)
• Pas d'index (COLLSCAN = full scan)
• $lookup partout (mauvaise modélisation)
• Stocker des fichiers dans MongoDB (S3)
• Ignorer la validation Mongoose
• Transactions multi-docs abusives
find() sans limit en production
• Pas de backup
• Collections au singulier (pluriel = convention)

🧠 Quiz
Embedding vs Referencing — comment choisir ?
Embedding = dans le même document. 1 seule requête, performances de lecture optimales. Pour : 1-to-1 ou 1-to-few, données toujours lues ensemble (user + adresse). Referencing = stocker un ID. Pour : 1-to-many (user → 1000 commandes), données modifiées indépendamment, risque de dépasser 16 Mo. Règle : « ce qui est lu ensemble vit ensemble ».
Pourquoi $match doit être en premier dans le pipeline ?
$match en premier réduit le volume traité par les étapes suivantes. En plus, un $match en début de pipeline utilise les index — les étapes suivantes travaillent sur un dataset réduit. Un $match au milieu du pipeline ne peut pas utiliser d'index. Différence : scanner 1M de documents vs 100.
Qu'est-ce qu'un ObjectId et pourquoi contient-il un timestamp ?
ObjectId = 12 octets : 4 octets de timestamp, 5 octets de valeur aléatoire, 3 octets de compteur. Le timestamp permet de trier par date de création sans champ supplémentaire. ObjectId(« … »).getTimestamp() retourne la date de création.

Cours MongoDB Complet — Documents, requêtes, agrégation, index, Mongoose et Atlas

Référence : MongoDB Docs | Mongoose | Atlas