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.

Questions / Réponses

Aucune question. Soyez le premier à poser une question.
Aucune note. Soyez le premier à attribuer une note !

Ajouter un commentaire

Anti-spam