cours MongoDB 01
Ce document vous donnes une couverture très large des commandes les plus utilisées et des familles de commandes indispensables (CRUD, index, agrégation, administration, utilisateurs, sauvegarde, etc.) avec des exemples concrets.
1)INTRODUCTION
MongoDB est une base de données NoSQL orientée documents, créée autour de 2009. Elle stocke les données sous forme de documents proches de JSON (en réalité BSON). L’idée : flexibilité (pas besoin d’un schéma strict) et facilité pour les applis web modernes.
Vocabulaire :
- Database : base de données
- Collection : “table” (mais flexible)
- Document : “ligne” (objet JSON)
- _id : identifiant unique (ObjectId) créé automatiquement
2) Pré-requis + installation (local)
2.1 Installer MongoDB + mongosh
- Installer MongoDB Community Server
- Installer mongosh (souvent inclus selon l’install)
2.2 Vérifier que ça marche
mongod --version
mongosh --version
2.3 Lancer le service MongoDB
Selon l’OS, MongoDB peut tourner comme un service. Si tu es sur Windows/Mac, c’est souvent automatique. Sinon :
mongod
2.4 Se connecter avec mongosh
mongosh
Tu peux aussi te connecter à un serveur distant :
mongosh "mongodb://localhost:27017"
3) Données fictives : société NkiliTech (ce qu’on va manipuler)
On va créer une base nkilitech avec plusieurs collections :
- employees : employés
- departments : départements
- products : produits
- orders : commandes clients
- tickets : tickets support
Exemples de documents :
employees:
{
nom: "Amina Nkili",
email: "amina@nkilitech.com",
role: "Dev",
departement: "Tech",
salaire: 3200,
competences: ["Node.js", "MongoDB"],
dateEmbauche: ISODate("2024-09-10"),
actif: true
}
orders:
{
numero: "CMD-10001",
client: { nom: "Koffi", pays: "FR" },
lignes: [
{ sku: "NT-KEY-01", nom: "NkiliKeyboard", prix: 49.9, qte: 2 },
{ sku: "NT-MOU-02", nom: "NkiliMouse", prix: 19.9, qte: 1 }
],
status: "PAID",
total: 119.7,
createdAt: ISODate("2025-01-03")
}
4) Commandes “shell” (mongosh) : navigation + infos
4.1 Lister les bases
show dbs
4.2 Choisir / créer une base (créée vraiment à l’insertion)
use nkilitech
db
4.3 Lister les collections
show collections
4.4 Aide (très utile)
help
db.help()
db.collection.help()
4.5 Informations serveur
db.version()
db.serverStatus()
db.stats()
5) Créer les données NkiliTech (INSERT)
5.1 departments
db.departments.insertMany([
{ nom: "Tech", budget: 200000, site: "Paris" },
{ nom: "Sales", budget: 150000, site: "Lyon" },
{ nom: "Support", budget: 80000, site: "Paris" }
])
5.2 employees
db.employees.insertMany([
{
nom: "Amina Nkili",
email: "amina@nkilitech.com",
role: "Dev",
departement: "Tech",
salaire: 3200,
competences: ["Node.js", "MongoDB"],
dateEmbauche: ISODate("2024-09-10"),
actif: true
},
{
nom: "Noah Kaba",
email: "noah@nkilitech.com",
role: "DevOps",
departement: "Tech",
salaire: 3800,
competences: ["Docker", "Linux", "CI/CD"],
dateEmbauche: ISODate("2023-05-20"),
actif: true
},
{
nom: "Lina Diallo",
email: "lina@nkilitech.com",
role: "Sales",
departement: "Sales",
salaire: 2800,
competences: ["CRM", "Nego"],
dateEmbauche: ISODate("2024-02-01"),
actif: true
}
])
5.3 products
db.products.insertMany([
{ sku: "NT-KEY-01", nom: "NkiliKeyboard", prix: 49.9, stock: 120, tags: ["hardware","keyboard"] },
{ sku: "NT-MOU-02", nom: "NkiliMouse", prix: 19.9, stock: 300, tags: ["hardware","mouse"] },
{ sku: "NT-CLD-10", nom: "NkiliCloud Basic", prix: 9.9, stock: null, tags: ["saas","cloud"] }
])
5.4 orders
db.orders.insertMany([
{
numero: "CMD-10001",
client: { nom: "Koffi", pays: "FR" },
lignes: [
{ sku: "NT-KEY-01", nom: "NkiliKeyboard", prix: 49.9, qte: 2 },
{ sku: "NT-MOU-02", nom: "NkiliMouse", prix: 19.9, qte: 1 }
],
status: "PAID",
total: 49.9*2 + 19.9*1,
createdAt: ISODate("2025-01-03")
},
{
numero: "CMD-10002",
client: { nom: "Sara", pays: "BE" },
lignes: [
{ sku: "NT-CLD-10", nom: "NkiliCloud Basic", prix: 9.9, qte: 6 }
],
status: "PENDING",
total: 9.9*6,
createdAt: ISODate("2025-01-05")
}
])
5.5 tickets
db.tickets.insertMany([
{
code: "TCK-9001",
client: "Koffi",
priorite: "HIGH",
sujet: "Clavier non reconnu",
status: "OPEN",
createdAt: ISODate("2025-01-04"),
messages: [
{ from: "client", text: "Mon clavier ne marche pas.", at: ISODate("2025-01-04") }
]
},
{
code: "TCK-9002",
client: "Sara",
priorite: "LOW",
sujet: "Facture",
status: "CLOSED",
createdAt: ISODate("2025-01-06"),
messages: [
{ from: "client", text: "Je veux la facture.", at: ISODate("2025-01-06") },
{ from: "support", text: "Envoyée par email.", at: ISODate("2025-01-06") }
]
}
])
6) READ : Toutes les variantes importantes de find()
6.1 Trouver tout
db.employees.find()
db.employees.find().pretty()
6.2 Filtrer (égalité)
db.employees.find({ departement: "Tech" })
6.3 Comparaisons
db.employees.find({ salaire: { $gt: 3000 } }) // >
db.employees.find({ salaire: { $gte: 3200 } }) // >=
db.employees.find({ salaire: { $lt: 3000 } }) // <
db.employees.find({ salaire: { $lte: 2800 } }) // <=
db.employees.find({ role: { $ne: "Dev" } }) // différent
6.4 IN / NOT IN
db.employees.find({ departement: { $in: ["Tech","Support"] } })
db.employees.find({ departement: { $nin: ["Sales"] } })
6.5 AND / OR / NOT
db.employees.find({ $and: [ { departement: "Tech" }, { salaire: { $gte: 3500 } } ] })
db.employees.find({ $or: [ { role: "Dev" }, { role: "DevOps" } ] })
db.employees.find({ departement: "Tech", salaire: { $gte: 3500 } }) // AND implicite
db.employees.find({ $nor: [ { role: "Sales" }, { salaire: { $lt: 3000 } } ] })
6.6 Champs manquants / null
db.products.find({ stock: null }) // stock null OU champ absent
db.products.find({ stock: { $exists: true } })
db.products.find({ stock: { $exists: false } })
6.7 Regex (recherche texte simple)
db.employees.find({ nom: { $regex: "^A", $options: "i" } }) // commence par A, insensible à la casse
6.8 Tableaux
db.employees.find({ competences: "MongoDB" }) // contient
db.products.find({ tags: { $all: ["hardware","mouse"] } }) // doit contenir les deux
db.orders.find({ "lignes.qte": { $gte: 2 } }) // un élément du tableau lignes a qte >= 2
6.9 Objets imbriqués (dot notation)
db.orders.find({ "client.pays": "FR" })
6.10 Projections (choisir les champs)
db.employees.find(
{ departement: "Tech" },
{ _id: 0, nom: 1, email: 1, salaire: 1 }
)
6.11 Tri, limite, skip
db.employees.find().sort({ salaire: -1 }) // décroissant
db.employees.find().sort({ salaire: 1 }) // croissant
db.employees.find().sort({ salaire: -1 }).limit(2)
db.employees.find().sort({ salaire: -1 }).skip(2).limit(2) // pagination
6.12 findOne
db.employees.findOne({ email: "amina@nkilitech.com" })
6.13 Compter
db.employees.countDocuments({})
db.orders.countDocuments({ status: "PAID" })
6.14 distinct
db.employees.distinct("departement")
db.orders.distinct("client.pays")
7) UPDATE : toutes les commandes importantes (updateOne / updateMany / replaceOne)
7.1 $set (modifier / ajouter un champ)
db.employees.updateOne(
{ email: "amina@nkilitech.com" },
{ $set: { salaire: 3300 } }
)
7.2 $unset (supprimer un champ)
db.employees.updateOne(
{ email: "amina@nkilitech.com" },
{ $unset: { actif: "" } }
)
7.3 $inc (incrémenter)
db.products.updateOne(
{ sku: "NT-KEY-01" },
{ $inc: { stock: -1 } }
)
7.4 $mul (multiplier)
db.products.updateOne(
{ sku: "NT-MOU-02" },
{ $mul: { prix: 1.05 } }
)
7.5 $rename (renommer un champ)
db.employees.updateMany(
{},
{ $rename: { "departement": "dept" } }
)
Attention : après ça, tes requêtes doivent utiliser dept au lieu de departement.
7.6 Tableaux : $push, $addToSet, $pull, $pop
// ajoute même s'il y a doublon
db.employees.updateOne(
{ email: "noah@nkilitech.com" },
{ $push: { competences: "Kubernetes" } }
)
// ajoute sans doublon
db.employees.updateOne(
{ email: "noah@nkilitech.com" },
{ $addToSet: { competences: "Linux" } }
)
// enlever un élément du tableau
db.employees.updateOne(
{ email: "noah@nkilitech.com" },
{ $pull: { competences: "Docker" } }
)
// retirer le dernier ou le premier
db.employees.updateOne(
{ email: "noah@nkilitech.com" },
{ $pop: { competences: 1 } } // 1 = dernier, -1 = premier
)
7.7 Upsert (créer si absent)
db.employees.updateOne(
{ email: "support@nkilitech.com" },
{ $set: { nom: "Support Bot", role: "Support", dept: "Support", salaire: 0 } },
{ upsert: true }
)
7.8 replaceOne (remplacer tout le document)
Attention : replaceOne remplace TOUT sauf _id. Si tu oublies un champ, il disparaît.
db.products.replaceOne(
{ sku: "NT-CLD-10" },
{ sku: "NT-CLD-10", nom: "NkiliCloud Basic", prix: 8.9, stock: null, tags: ["saas","cloud"] }
)
7.9 findOneAndUpdate (mettre à jour et récupérer)
db.tickets.findOneAndUpdate(
{ code: "TCK-9001" },
{ $set: { status: "IN_PROGRESS" } },
{ returnDocument: "after" }
)
8) DELETE : deleteOne / deleteMany + prudence
db.tickets.deleteOne({ code: "TCK-9002" })
db.orders.deleteMany({ status: "PENDING" })
Tip sécurité : avant un deleteMany, fais toujours un find avec le même filtre :
db.orders.find({ status: "PENDING" })
9) Index : createIndex, getIndexes, dropIndex (performance)
9.1 Index simple
db.employees.createIndex({ email: 1 })
9.2 Index unique (empêche doublons)
db.employees.createIndex({ email: 1 }, { unique: true })
9.3 Index composé
db.orders.createIndex({ status: 1, createdAt: -1 })
9.4 Index texte (recherche textuelle)
db.tickets.createIndex({ sujet: "text" })
db.tickets.find({ $text: { $search: "facture clavier" } })
9.5 Voir / supprimer des index
db.employees.getIndexes()
db.employees.dropIndex({ email: 1 })
9.6 Expliquer une requête (voir si index utilisé)
db.employees.find({ email: "amina@nkilitech.com" }).explain("executionStats")
10) Aggregation Pipeline : les étapes les plus importantes
L’agrégation = une suite d’étapes. Les plus importantes :
- $match : filtrer
- $project : choisir / transformer des champs
- $group : regrouper + calcul (avg, sum, min, max)
- $sort : trier
- $limit / $skip : pagination
- $unwind : “déplier” un tableau
- $lookup : “jointure” entre collections
10.1 Exemple : total des ventes payées par pays
db.orders.aggregate([
{ $match: { status: "PAID" } },
{ $group: { _id: "$client.pays", totalVentes: { $sum: "$total" }, nbCommandes: { $sum: 1 } } },
{ $sort: { totalVentes: -1 } }
])
10.2 Exemple : analyser les lignes de commande (unwind)
db.orders.aggregate([
{ $unwind: "$lignes" },
{ $group: { _id: "$lignes.sku", qteTotale: { $sum: "$lignes.qte" } } },
{ $sort: { qteTotale: -1 } }
])
10.3 Exemple : “jointure” orders -> products (lookup)
db.orders.aggregate([
{ $unwind: "$lignes" },
{
$lookup: {
from: "products",
localField: "lignes.sku",
foreignField: "sku",
as: "produit"
}
},
{ $unwind: "$produit" },
{
$project: {
_id: 0,
numero: 1,
sku: "$lignes.sku",
nomProduit: "$produit.nom",
prixCatalogue: "$produit.prix",
qte: "$lignes.qte"
}
}
])
11) Outils “administration” (db + collections)
11.1 Stats base + collection
db.stats()
db.employees.stats()
11.2 Renommer collection
db.tickets.renameCollection("supportTickets")
11.3 Supprimer collection / base
db.supportTickets.drop()
db.dropDatabase()
Attention : drop() et dropDatabase() suppriment définitivement.
12) Validation (schéma) : rendre une collection plus “propre”
MongoDB est flexible, mais tu peux ajouter des règles avec un validateur. Exemple : employees doit avoir nom (string), email (string) et salaire (number).
db.createCollection("employeesStrict", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["nom", "email", "salaire"],
properties: {
nom: { bsonType: "string" },
email: { bsonType: "string" },
salaire: { bsonType: "number" }
}
}
}
})
13) Utilisateurs et rôles (sécurité) – base
Ces commandes marchent surtout quand l’authentification est activée.
13.1 Créer un utilisateur
use admin
db.createUser({
user: "adminNkili",
pwd: "motdepasseFort",
roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
})
13.2 Lister les utilisateurs
db.getUsers()
13.3 Donner un rôle / changer mot de passe
db.grantRolesToUser("adminNkili", [ { role: "readWriteAnyDatabase", db: "admin" } ])
db.changeUserPassword("adminNkili", "nouveauMotDePasse")
13.4 Supprimer un utilisateur
db.dropUser("adminNkili")
14) Import / Export (très pratique)
Ces commandes sont des outils en ligne de commande (pas dans mongosh) :
14.1 Exporter en JSON (mongoexport)
mongoexport --db nkilitech --collection employees --out employees.json
14.2 Importer un JSON (mongoimport)
mongoimport --db nkilitech --collection employees --file employees.json --jsonArray
14.3 Sauvegarde complète (mongodump) + restauration (mongorestore)
mongodump --db nkilitech --out backup_nkilitech
mongorestore --db nkilitech backup_nkilitech/nkilitech
15) Tips (super importants) pour éviter les erreurs
- Astuce 1 : Avant un
deleteMany, fais toujours un find avec le même filtre.
- Astuce 2 : Utilise des index sur les champs très recherchés (email, status, dates).
- Astuce 3 : Évite
replaceOne si tu n’es pas sûr : tu peux perdre des champs.
- Astuce 4 : Utilise
explain() pour comprendre les performances.
- Astuce 5 : Sois cohérent : mêmes noms de champs partout (ex: dept vs departement).
16) “Cheat Sheet” final (résumé rapide)
# Navigation
show dbs
use nkilitech
show collections
db.stats()
# Create
db.collection.insertOne({})
db.collection.insertMany([])
# Read
db.collection.find({})
db.collection.find({ champ: valeur })
db.collection.find({ champ: { $gte: 10 } })
db.collection.find({}, { champ1: 1, _id: 0 })
db.collection.find().sort({ champ: -1 }).limit(10).skip(10)
db.collection.findOne({})
db.collection.countDocuments({})
db.collection.distinct("champ")
# Update
db.collection.updateOne(filter, update, options)
db.collection.updateMany(filter, update, options)
$set, $unset, $inc, $mul, $rename, $push, $addToSet, $pull, $pop
db.collection.replaceOne(filter, doc)
db.collection.findOneAndUpdate(filter, update, { returnDocument: "after" })
# Delete
db.collection.deleteOne(filter)
db.collection.deleteMany(filter)
# Index
db.collection.createIndex({ champ: 1 })
db.collection.createIndex({ champ: 1 }, { unique: true })
db.collection.getIndexes()
db.collection.dropIndex({ champ: 1 })
db.collection.find(filter).explain("executionStats")
# Aggregation
db.collection.aggregate([ { $match: {} }, { $group: {} }, { $sort: {} } ])
# Export / Import (CLI)
mongoexport / mongoimport
mongodump / mongorestore
17) Exercice rapide (avec NkiliTech)
Exercice : Affiche les commandes PAID du pays FR en ne montrant que numero, total, createdAt, triées par date décroissante.
db.orders.find(
{ status: "PAID", "client.pays": "FR" },
{ _id: 0, numero: 1, total: 1, createdAt: 1 }
).sort({ createdAt: -1 })
Exercice : Calcule la quantité totale vendue par SKU sur les commandes PAID.
db.orders.aggregate([
{ $match: { status: "PAID" } },
{ $unwind: "$lignes" },
{ $group: { _id: "$lignes.sku", qteTotale: { $sum: "$lignes.qte" } } },
{ $sort: { qteTotale: -1 } }
])
Fin du document.