Votre progression

Continuez pour débloquer la suite !
0 / 0 étapes complétées 0
%
  1. Présentation du cours

    1. Public cible

      Ce cours s'adresse aux :

      • Développeurs full-stack ou back-end
      • Data analysts et data scientists
      • Administrateurs de bases de données
      • Architectes solutions cloud
      • Étudiants en informatique
    2. Objectifs d'apprentissage

      À l'issue de cette formation, vous serez capable de :

      Comprendre les concepts fondamentaux des bases de données NoSQL
      Maîtriser les opérations CRUD avec MongoDB
      Concevoir des schémas de documents efficaces
      Mettre en place des agrégations complexes
      Optimiser les performances des requêtes
      Intégrer MongoDB dans un écosystème Big Data
    3. Prérequis

      Connaissances de base

      • Concepts fondamentaux des bases de données
      • Notions de programmation (JavaScript ou Python)
      • Bases du langage JSON

      Environnement technique

      • Accès à un ordinateur avec 4 Go de RAM minimum
      • Connexion Internet stable
      • Droits d'administration pour l'installation de logiciels
    4. Durée et organisation

      ~40 heures de formation

      Réparties sur plusiers séquences

      Contenu pédagogique

      • modules théoriques
      • exercices pratiques
      • projets fil rouge
      • examens

      Planning type

      • en fonction du niveau et du temps disponible
      • Accès 24/7 aux ressources en ligne
      • Support pédagogique inclus
  2. Introduction à MongoDB

    Écosystème et Architecture de MongoDB

    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% flowchart TD classDef cloud fill:#13AA52,color:white,stroke:#0d6e0d; classDef enterprise fill:#5d9cec,color:white,stroke:#2c3e50; classDef tools fill:#a0d468,color:white,stroke:#5d7c1d; classDef router fill:#2c3e50,color:white,stroke:#1a252f; classDef config fill:#8e44ad,color:white,stroke:#5d2d7d; classDef primary fill:#e74c3c,color:white,stroke:#c0392b; classDef secondary fill:#f39c12,color:white,stroke:#d68910; classDef storage fill:#3498db,color:white,stroke:#2980b9; subgraph "MongoDB Ecosystem" direction TB subgraph "MongoDB Atlas (Cloud)" direction TB A1[fa:fa-cloud Atlas UI] <--> A2[fa:fa-cogs Atlas API] A2 <--> A3[fa:fa-database Atlas Data Lake] A2 <--> A4[fa:fa-search Atlas Search] A2 <--> A5[fa:fa-mobile-alt Atlas Device Sync] end subgraph "MongoDB Enterprise (On-Premise)" direction TB E1[fa:fa-tachometer-alt Ops Manager] <--> E2[fa:fa-server Enterprise Server] E1 <--> E3[fa:fa-chart-line Monitoring] E1 <--> E4[fa:fa-hdd Backup] end subgraph "MongoDB Tools" direction TB T1[fa:fa-compass Compass] <--> T2[fa:fa-tools Database Tools] T3[fa:fa-terminal MongoDB Shell] <--> T4[fa:fa-plug Drivers] T5[fa:fa-plug Connectors] <--> T6[fa:fa-chart-bar BI Connector] end subgraph "MongoDB Cluster" direction TB subgraph "Mongos Routers" M1["fa:fa-route Mongos 1 --- 🔍 Routeur de requêtes 📦 Cache de métadonnées ⚖️ Équilibrage de charge"] M2["fa:fa-route Mongos 2 --- 🔍 Routeur de requêtes 📦 Cache de métadonnées ⚖️ Équilibrage de charge"] end subgraph "Config Servers (C1, C2, C3)" C1["fa:fa-cog Config 1 --- 📋 Métadonnées 🗺️ Mapping des shards 🔄 Réplication"] C2[fa:fa-cog Config 2] <--> C1 C2 <--> C3[fa:fa-cog Config 3] end subgraph "Shard 1 (S1)" direction TB S1P["fa:fa-star Primary --- ✏️ Écritures 🔄 Réplication 👑 Leader"] S1P -->|réplique| S1S1["fa:fa-clone Secondary 1 --- 📥 Réplication 👁️ Lecture seule 🔄 Candidat à l'élection"] S1P -->|réplique| S1S2[fa:fa-clone Secondary 2] end subgraph "Shard 2 (S2)" direction TB S2P[fa:fa-star Primary] -->|réplique| S2S1[fa:fa-clone Secondary 1] S2P -->|réplique| S2S2[fa:fa-clone Secondary 2] end M1 -->|route| S1P M1 -->|route| S2P M1 -->|métadonnées| C1 M2 -->|route| S1P M2 -->|route| S2P M2 -->|métadonnées| C1 end %% Connexions entre les composants A2 -.-> M1 A2 -.-> M2 E1 -.-> S1P E1 -.-> S2P T1 --> M1 T1 --> M2 T3 --> M1 T3 --> M2 %% Classes CSS class A1,A2,A3,A4,A5 cloud; class E1,E2,E3,E4 enterprise; class T1,T2,T3,T4,T5,T6 tools; class M1,M2 router; class C1,C2,C3 config; class S1P,S2P primary; class S1S1,S1S2,S2S1,S2S2 secondary; %% Légende legend[fa:fa-list Legend] legend --> cloud_legend[Cloud Services] legend --> enterprise_legend[Enterprise Tools] legend --> tools_legend[Client Tools] legend --> router_legend[Routeur Mongos] legend --> config_legend[Config Servers] legend --> primary_legend[Nœud Primaire] legend --> secondary_legend[Nœud Secondaire] class legend,cloud_legend,enterprise_legend,tools_legend,router_legend,config_legend,primary_legend,secondary_legend legend-style; classDef legend-style fill:#f8f9fa,stroke:#ddd,stroke-width:1px,color:#333,padding:5px,font-size:12px; end
    Figure 1 : Vue d'ensemble de l'écosystème et de l'architecture MongoDB

    Explication du schéma :

    MongoDB Atlas (Cloud)

    Solution cloud complète avec interface de gestion, API, data lake et synchronisation mobile.

    MongoDB Enterprise

    Version auto-hébergée avec outils de gestion, surveillance et sauvegarde.

    Outils Clients

    Applications et bibliothèques pour interagir avec MongoDB (Compass, Shell, Drivers).

    Architecture du Cluster
    • Routeurs Mongos : Point d'entrée des requêtes clientes
    • Config Servers (C1-C3) : Stockent les métadonnées du cluster
    • Shards (S1-S2) : Stockent les données (chaque shard est un replica set)
    • Replica Sets : Groupes de nœuds (1 Primaire + Secondaires) pour la haute disponibilité

    Qu'est-ce que MongoDB ?

    MongoDB est une base de données NoSQL orientée documents, classée parmi les bases de données les plus populaires au monde. Contrairement aux bases de données relationnelles traditionnelles, MongoDB stocke les données sous forme de documents flexibles et évolutifs, ce qui en fait un choix idéal pour les applications modernes.

    À retenir

    • MongoDB est une base de données NoSQL orientée documents
    • Stockage des données en format BSON (JSON binaire)
    • Modèle de données flexible et sans schéma imposé
    • Idéal pour les applications nécessitant une grande évolutivité

    Caractéristiques clés :

    Modèle de documents

    Stockage des données en format BSON (binaire JSON) pour une grande flexibilité

    Évolutivité horizontale

    Distribution des données via le sharding pour gérer de grandes charges

    Haute performance

    Indexation avancée et accès mémoire pour des temps de réponse rapides

    Sécurité renforcée

    Chiffrement, authentification et RBAC (contrôle d'accès basé sur les rôles)

    Points clés

    • Modèle de données flexible avec BSON
    • Évolutivité horizontale via le partitionnement (sharding)
    • Performances optimisées avec indexation et cache mémoire
    • Sécurité complète avec chiffrement et contrôle d'accès fin

    Cas d'utilisation

    Applications mobiles

    Stockage flexible pour les données utilisateur et le contenu des applications mobiles avec synchronisation hors ligne.

    E-commerce

    Gestion de catalogues produits complexes avec des attributs variables selon les catégories.

    Analytique en temps réel

    Analyse de données massives avec des agrégations puissantes et des pipelines de traitement.

    Réseaux sociaux

    Gestion des profils utilisateurs, des publications et des interactions sociales avec des schémas évolutifs.

    Écosystème MongoDB

    MongoDB Atlas

    Service cloud entièrement géré pour MongoDB, offrant évolutivité et haute disponibilité.

    MongoDB Compass

    Interface graphique officielle pour explorer et analyser vos données MongoDB.

    MongoDB Shell

    Interface en ligne de commande (CLI) interactive pour administrer et interroger MongoDB.

    MongoDB Realm

    Plateforme de développement d'applications avec synchronisation des données en temps réel.

    Écosystème clé en main

    • Atlas : Solution cloud complète avec automatisation des opérations
    • Compass : GUI pour visualiser et analyser les données
    • Shell : Interface ligne de commande avancée
    • Realm : Développement d'applications mobiles et web temps réel

    Modèle de documents

    Contrairement aux bases de données relationnelles qui utilisent des tables et des lignes, MongoDB stocke les données sous forme de documents au format BSON (binaire JSON).

    Avantages

    • Schéma dynamique pour une grande flexibilité
    • Structure hiérarchique des données
    • Support natif des tableaux et documents imbriqués
    • Représentation plus naturelle des données pour les développeurs

    Exemple de document

    {
      "_id": ObjectId("5f8d8d8d8d8d8d8d8d8d8d8d"),
      "titre": "Le Seigneur des Anneaux",
      "annee": 2001,
      "duree": 178,
      "genres": ["Aventure", "Fantasy", "Action"],
      "realisateur": {
        "nom": "Jackson",
        "prenom": "Peter"
      },
      "acteurs": ["Elijah Wood", "Ian McKellen", "Viggo Mortensen"],
      "pays": "Nouvelle-Zélande",
      "note_imdb": 8.8
    }

    Architecture de MongoDB

    Architecture de MongoDB

    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% graph TD subgraph "MongoDB Cluster" subgraph "Shard 1" direction TB P1[Primary] -->|réplication| S1a[Secondary 1] P1 -->|réplication| S1b[Secondary 2] end subgraph "Shard 2" direction TB P2[Primary] -->|réplication| S2a[Secondary 1] P2 -->|réplication| S2b[Secondary 2] end subgraph "Config Servers" direction TB C1[Config 1] <--> C2[Config 2] C2 <--> C3[Config 3] end Mongos1[Mongos Router] -->|route| P1 Mongos1 -->|route| P2 Mongos1 -->|métadonnées| C1 App[Application] --> Mongos1 end style App fill:#13AA52,color:white,stroke:#0d6e0d style Mongos1 fill:#2c3e50,color:white style C1,C2,C3 fill:#5d9cec,color:white style P1,P2 fill:#48cfad,color:white style S1a,S1b,S2a,S2b fill:#a0d468,color:white
    Figure 1 : Architecture MongoDB avec Sharding et Réplication

    MongoDB est conçu pour être hautement évolutif et disponible. Voici ses composants clés :

    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% classDiagram class BaseDeDonnees { +string nom +Collection[] collections } class Collection { +string nom +Document[] documents +createIndex() +find() +insertOne() +updateMany() +aggregate() } class Document { +ObjectId _id +any champs +Date dateCreation +save() +update() +delete() } BaseDeDonnees "1" *-- "0..*" Collection : contient Collection "1" *-- "0..*" Document : contient
    Figure 2 : Modèle de données de MongoDB

    Structure de base

    Document

    Unité de base des données, stockée en format BSON (binaire JSON). Peut contenir des tableaux et des documents imbriqués.

    Collection

    Groupe de documents, équivalent à une table dans les bases relationnelles. Pas de schéma imposé.

    Base de données

    Conteneur pour les collections, avec son propre ensemble de fichiers sur le système de fichiers.

    Structure de base

    • Document : Unité de base en BSON (comme JSON mais binaire)
    • Collection : Groupe de documents (équivalent aux tables SQL)
    • Base de données : Conteneur logique pour les collections
    • Schéma dynamique : Pas de structure fixe imposée
    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% graph TD classDef database fill:#13AA52,color:white,stroke:#0d6e0d; classDef collection fill:#5d9cec,color:white,stroke:#2c3e50; classDef document fill:#a0d468,color:white,stroke:#5d7c1d; %% Base de données DB[(Base de données)]:::database %% Collection Utilisateurs DB --> C1[Utilisateurs]:::collection C1 --> D1["{\n _id: ObjectId('...')\n nom: 'Dupont'\n email: 'jean@exemple.com'\n }"]:::document %% Collection Produits DB --> C2[Produits]:::collection C2 --> P1["{\n _id: ObjectId('...')\n nom: 'Ordinateur'\n prix: 999.99\n }"]:::document %% Légende L1[Base de données]:::database L2[Collection]:::collection L3[Document]:::document
    Figure 3 : Structure hiérarchique de MongoDB

    Légende :

    Base de données
    Collection
    Document (BSON)

    Sharding (Partitionnement)

    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% flowchart LR A[Application] --> B[Mongos Router] B -->|Requête| C[Config Servers] B -->|Route| D[Shard 1] B -->|Route| E[Shard 2] B -->|Route| F[Shard 3] subgraph "Shard 1" D1[Primary] --> D2[Secondary] D1 --> D3[Secondary] end subgraph "Shard 2" E1[Primary] --> E2[Secondary] E1 --> E3[Secondary] end subgraph "Shard 3" F1[Primary] --> F2[Secondary] F1 --> F3[Secondary] end style A fill:#13AA52,color:white,stroke:#0d6e0d style B fill:#2c3e50,color:white style C fill:#5d9cec,color:white style D1,E1,F1 fill:#48cfad,color:white style D2,D3,E2,E3,F2,F3 fill:#a0d468,color:white
    Figure 3 : Architecture de Sharding dans MongoDB

    MongoDB utilise le partitionnement horizontal pour répartir les données sur plusieurs machines :

    • Shard : Instance MongoDB contenant un sous-ensemble des données (partition)
    • Config Server : Stocke les métadonnées du cluster (état du sharding)
    • Mongos : Routeur de requêtes qui aiguille vers les bons shards
    • Shard Key : Champ utilisé pour répartir les données entre les shards

    Points clés du Sharding

    • Distribution horizontale des données sur plusieurs serveurs
    • Shard Key : Clé de partitionnement critique pour les performances
    • Mongos : Point d'entrée unique pour les applications
    • Équilibrage automatique des données entre les shards

    Avantages :

    • Distribution de la charge de lecture/écriture
    • Capacité de stockage illimitée
    • Haute disponibilité et tolérance aux pannes
    • Évolutivité linéaire en ajoutant des shards
    Mongos Router
    Shard 1
    Primary
    Secondary
    Secondary
    Shard 2
    Secondary
    Primary
    Secondary
    Config Servers
    C1
    C2
    C3

    Réplication

    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% sequenceDiagram participant C as Client participant P as Primary participant S1 as Secondary 1 participant S2 as Secondary 2 C->>P: Écriture des données P-->>C: Accusé réception par Réplication P->>S1: Oplog Entry 1 P->>S2: Oplog Entry 1 S1-->>P: Accusé S2-->>P: Accusé P->>S1: Oplog Entry 2 P->>S2: Oplog Entry 2 S1-->>P: Accusé S2-->>P: Accusé end Note over P: Heartbeat régulier alt Défaillance du Primary S1->>S2: Élection S2-->>S1: Vote S1->>P: Step Down S1->>C: Nouveau Primary end
    Figure 4 : Processus de réplication et élection dans un Replica Set

    MongoDB utilise des ensembles de réplication (Replica Sets) pour assurer la haute disponibilité :

    • Primary : Nœud qui reçoit toutes les opérations d'écriture (oplog)
    • Secondaries : Nœuds qui répliquent les données du primary (synchrone/asynchrone)
    • Arbiter : Nœud spécial qui participe aux élections mais ne stocke pas de données
    • Oplog : Journal des opérations pour la réplication

    Points clés de la Réplication

    • Haute disponibilité avec basculement automatique
    • Répartition de la charge de lecture sur les secondaires
    • Oplog : Journal des opérations pour la synchronisation
    • Élections automatiques pour le nouveau primary en cas de défaillance

    Avantages :

    • Haute disponibilité (basculement automatique en cas de panne)
    • Récupération après sinistre avec les données à jour
    • Possibilité de lectures locales depuis les secondaires
    • Maintenance sans interruption de service

    Primary

    Reçoit toutes les opérations d'écriture (oplog)

    Secondaries

    Reproduisent les opérations du primary. Peuvent être utilisés pour les lectures.

    Arbiter

    Ne stocke pas de données, participe uniquement aux élections.

    Performance et optimisation

    Indexation

    MongoDB prend en charge différents types d'index pour optimiser les performances :

    • Index unique : Garantit l'unicité des valeurs
    • Index composé : Sur plusieurs champs
    • Index géospatial : Pour les requêtes de localisation
    • Index de texte : Pour la recherche plein texte
    • Index TTL : Pour l'expiration des documents

    Stockage en mémoire

    MongoDB utilise la mémoire pour optimiser les performances :

    • Cache des documents fréquemment accédés
    • Moteur de stockage WiredTiger avec compression
    • Gestion efficace des E/S disque
    • Journalisation pour la durabilité

    Agrégation

    Pipeline d'agrégation puissant pour le traitement des données :

    %%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#e1f5e1', 'primaryTextColor': '#0d6e0d', 'primaryBorderColor': '#13AA52'}}}%% flowchart LR A[Collection] --> B[$match] B --> C[$group] C --> D[$sort] D --> E[$project] E --> F[Résultats] style A fill:#a0d468,color:white style B fill:#5d9cec,color:white style C fill:#5d9cec,color:white style D fill:#5d9cec,color:white style E fill:#5d9cec,color:white style F fill:#48cfad,color:white
    Figure 5 : Pipeline d'agrégation MongoDB
    • $match : Filtrage des documents
    • $group : Regroupement et calculs
    • $sort et $limit : Tri et limitation
    • $lookup : Jointures entre collections
    • $facet : Agrégations multiples en parallèle
    // Exemple de pipeline d'agrégation
    db.orders.aggregate([
      { $match: { status: "completed" } },
      { $group: {
          _id: "$customer_id",
          total: { $sum: "$amount" },
          count: { $sum: 1 }
      }},
      { $sort: { total: -1 } },
      { $limit: 10 }
    ])

    Optimisation des performances

    • Indexation stratégique pour les requêtes fréquentes
    • Utilisation de la RAM pour le cache des données
    • Sharding pour la distribution de la charge
    • Optimisation du schéma de données pour les cas d'usage
    • Surveillance avec MongoDB Atlas ou MongoDB Ops Manager

    Concepts avancés

    Sécurité avancée

    • Chiffrement au repos avec WiredTiger
    • RBAC (Role-Based Access Control)
    • Intégration LDAP et Kerberos
    • Audit des opérations
    • Chiffrement côté client
    Points clés sécurité
    • Authentification et autorisation avancées
    • Chiffrement des données sensibles
    • Audit des opérations critiques
    • Intégration avec les systèmes d'entreprise

    Transactions ACID

    • Support des transactions multi-documents
    • Niveaux d'isolation configurables
    • Optimisation pour les clusters distribués
    • Gestion des conflits
    • Support des opérations atomiques
    Transactions
    • ACID : Atomicité, Cohérence, Isolation, Durabilité
    • Transactions multi-documents
    • Support dans les environnements distribués
    • Gestion des conflits et des verrous

    Modélisation des données

    • Patterns de conception (Bucket, Subset, etc.)
    • Relations (références vs embedding)
    • Optimisation des schémas pour les requêtes
    • Gestion des hiérarchies complexes
    • Approche sans schéma mais avec validation
    Modélisation
    • Choix entre embedding et références
    • Optimisation pour les cas d'usage courants
    • Gestion des relations entre documents
    • Validation des schémas optionnelle
  3. Installation et configuration

    1. Installation sur différentes plateformes

      1. Windows :

        1. 1. Télécharger l'installeur sur https://www.mongodb.com/try/download/community
        2. 2. Suivre l'assistant d'installation
        3. 3. Lancer le service MongoDB depuis les Services Windows ou en ligne de commande
      2. macOS :

        1. brew tap mongodb/brew
        2. brew install mongodb-community@7.0
        3. brew services start mongodb-community@7.0
      3. Linux (Ubuntu/Debian) :

        1. wget -qO - https://www.mongodb.org/static/pgp/server-7.0.asc | sudo apt-key add -
        2. echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/7.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-7.0.list
        3. sudo apt-get update
        4. sudo apt-get install -y mongodb-org
        5. sudo systemctl start mongod
    2. Configuration initiale

      1. mongod.conf

        1. configurer le port

          Le fichier mongod.conf permet de configurer le port, le répertoire de données, la sécurité, etc.

          # Extrait minimal de mongod.conf
                                                                storage:
                                                                  dbPath: /var/lib/mongodb
                                                                data:
                                                                  bindIp: 127.0.0.1
                                                                net:
                                                                  port: 27017
                                                                security:
                                                                  authorization: enabled
                                                
      2. Lancer le serveur

        Pour lancer et arrêter le serveur :
        
                                  # Démarrer
                                  sudo systemctl start mongod
                                  # Arrêter
                                  sudo systemctl stop mongod
                                
      3. Connexion au serveur MongoDB

        • MongoDB Shell (mongosh) :
          
                                      # Se connecter localement
                                      mongosh
                                      # Se connecter à une base distante
                                      mongosh "mongodb+srv://:@cluster0.mongodb.net/test"
                                    
        • MongoDB Compass (GUI) : Application graphique pour explorer visuellement vos bases et collections, faire des requêtes, importer/exporter des données, etc. Aperçu MongoDB Compass
      4. Astuce

        Pour des tests rapides, MongoDB Atlas propose une instance cloud gratuite, sans installation locale.

    3. Quiz

      Quel est le port par défaut utilisé par MongoDB?

    4. QCM

      Quel outil permet d’explorer graphiquement les bases MongoDB ?




  4. Découverte de MongoDB Atlas

    1. Présentation générale

      MongoDB Atlas est la plateforme cloud officielle de MongoDB, qui permet de déployer, gérer et faire évoluer des bases de données MongoDB dans le cloud (AWS, Azure, GCP).
    2. Avantages du cloud

      • Haute disponibilité (réplication multi-zone)
      • Sauvegardes automatiques
      • Scalabilité à la demande
      • Maintenance et mises à jour simplifiées
    3. Mise en place d'un compte Atlas

      1. Créer un compte sur mongodb.com/cloud/atlas
      2. Créer un cluster gratuit (M0)
      3. Configurer un utilisateur et une whitelist d’IP
      4. Se connecter via Compass ou mongosh
    4. Interface MongoDB Atlas

      1. Vue d'ensemble de l'interface

        graph TD A[Atlas UI] --> B[API Gateway] B --> C[Authentication Service] B --> D[Cluster Manager] D --> E[Database Services] D --> F[Monitoring] D --> G[Backup Services]
      2. Configuration d'un cluster

        Configuration d'un Cluster

        Paramètres principaux

        Paramètres avancés

        Paramètres de sécurité

        Paramètres principaux lors de la création d'un cluster :

        • Cloud Provider : AWS, Azure ou GCP
        • Region : Choisir la région la plus proche
        • Cluster Tier : M0 (gratuit), M2, M5, etc.
        • Replica Set : Pour la haute disponibilité
        • Sharding : Pour la scalabilité horizontale
      3. Connexion à la base de données

        1. MongoDB Compass

        Interface graphique pour explorer et gérer votre base de données

        • Interface intuitive
        • Opérations CRUD
        • Visualisation des données
        • Import/Export

        2. mongosh (MongoDB Shell)

        Ligne de commande pour interagir avec MongoDB

        Exemple de connexion

        const { MongoClient } = require('mongodb');
        const uri = "mongodb+srv://username:password@cluster0.mongodb.net";
        const client = new MongoClient(uri);
        

        3. Programmation

        Node.js

        const { MongoClient } = require('mongodb');
        const uri = "mongodb+srv://username:password@cluster0.mongodb.net";
        const client = new MongoClient(uri);
        

        Python

        from pymongo import MongoClient
        uri = "mongodb+srv://username:password@cluster0.mongodb.net"
        client = MongoClient(uri)
        

        Java

        MongoClient mongoClient = MongoClients.create(
            "mongodb+srv://username:password@cluster0.mongodb.net"
        );
        

        Scala

        val client = MongoClient(
            "mongodb+srv://username:password@cluster0.mongodb.net"
        )
        
      4. Configuration de sécurité

        1. Gestion des utilisateurs

        Création d'un utilisateur avec les droits nécessaires

        Exemple de création d'utilisateur

        db.createUser({
          user: "myapp",
          pwd: "secure_password",
          roles: [
            { role: "readWrite", db: "myapp" },
            { role: "dbAdmin", db: "myapp" }
          ]
        });
        

        Rôles MongoDB

        Rôles de lecture/écriture
        • read : Lecture seule
        • readWrite : Lecture et écriture
        • readWriteAnyDatabase : Accès à toutes les bases
        Rôles d'administration
        • dbAdmin : Administration de la base
        • dbOwner : Propriétaire de la base
        • userAdmin : Gestion des utilisateurs
        Rôles système
        • clusterAdmin : Administration du cluster
        • clusterManager : Gestion du cluster
        • clusterMonitor : Surveillance du cluster
        Rôles spéciaux
        • root : Accès complet
        • backup : Sauvegarde
        • restore : Restauration
        Recommandations d'utilisation
        • Utiliser le principe du moindre privilège
        • Éviter les rôles root et admin sauf nécessité
        • Créer des rôles personnalisés si nécessaire
        • Séparer les rôles d'administration et d'application
        • Documenter les rôles utilisés

        2. Contrôle d'accès IP

        Configuration des IP autorisées

        Exemple de configuration

        # IP spécifique
        192.168.1.100/32
        
        # Plage d'IP
        192.168.1.0/24
        
        # IP dynamique (avec masque)
        192.168.1.0/28
        
        • Éviter l'IP 0.0.0.0/0 (toutes les IP)
        • Utiliser des plages d'IP spécifiques
        • Supprimer les IP non utilisées
        • Utiliser des masques de sous-réseau appropriés

        3. Authentification forte

        Configuration de l'authentification

        • Mots de passe complexes (12 caractères minimum)
        • Rotation des mots de passe
        • Utilisation de certificats X.509
        • Authentification multi-facteurs (MFA)
        • Expiration des sessions inactives

        4. Encryption en transit

        Configuration de l'encryption

        • Utiliser TLS/SSL pour toutes les connexions
        • Version TLS 1.2 minimum
        • Validation des certificats
        • Configuration des certificats client
        • Monitoring des connexions non sécurisées
      5. Meilleures pratiques

        1. Sécurité

        • Utiliser un réseau privé virtuel (VPN)
        • Activer l'audit des opérations
        • Limiter les connexions simultanées
        • Sauvegarder régulièrement les données
        • Surveiller les tentatives de connexion

        2. Performance

        • Indexer les champs fréquemment utilisés
        • Optimiser les requêtes complexes
        • Utiliser le sharding pour les gros volumes
        • Limiter le nombre de documents retournés
        • Utiliser les projections pour les champs

        3. Maintenance

        • Planifier les sauvegardes
        • Surveiller l'utilisation des ressources
        • Documenter la structure des données
        • Mettre à jour régulièrement
        • Tester les modifications avant production

        4. Bonnes pratiques de développement

        • Utiliser des schémas bien définis
        • Éviter les documents trop volumineux
        • Utiliser les transactions quand nécessaire
        • Implémenter la pagination
        • Gérer les erreurs de connexion

        5. Surveillance

        • Activer les logs
        • Surveiller les performances
        • Configurer les alertes
        • Analyser les métriques
        • Documenter les incidents
    5. Quiz

      Citez deux avantages de MongoDB Atlas par rapport à une installation locale.
    6. QCM

      MongoDB Atlas permet :




  5. Les Fondamentaux de MongoDB

    1. Introduction à MongoDB et aux bases NoSQL

      1. Qu'est-ce que MongoDB ?

        MongoDB est une base de données NoSQL orientée document, conçue pour la flexibilité, la scalabilité horizontale et les performances élevées.

        graph TD %% Niveaux principaux A[MongoDB] --> B[Base de données] B --> C[Collection] C --> D[Document] %% Documents dans la collection C --> Doc1[Document 1] C --> Doc2[Document 2] C --> Doc3[Document ...] %% Structure d'un document Doc1 --> Field1[_id: ObjectId] Doc1 --> Field2[nom] Doc1 --> Field3[email] Doc1 --> Field4[adresse] %% Styles de base style A fill:#4db8ff,stroke:#4db8ff,color:white style B fill:#4db8ff,stroke:#4db8ff,color:white style C fill:#ff6b6b,stroke:#ff6b6b,color:white style Doc1 fill:#6c5ce7,stroke:#6c5ce7,color:white,stroke-dasharray: 5 5 style Doc2 fill:#6c5ce7,stroke:#6c5ce7,color:white,stroke-dasharray: 5 5 style Doc3 fill:#6c5ce7,stroke:#6c5ce7,color:white,stroke-dasharray: 5 5
        Les collections MongoDB

        Une collection dans MongoDB est un groupe de documents, équivalent à une table dans les bases de données relationnelles. Cependant, contrairement aux tables, les collections n'imposent pas de schéma strict.

        Caractéristiques des collections :
        • Pas de schéma imposé : les documents d'une même collection peuvent avoir des structures différentes
        • Haute performance : optimisées pour les opérations de lecture/écriture
        • Indexables : permet des recherches rapides
        Bon à savoir : Par convention, les noms de collections sont au pluriel (ex: users, orders).

        Figure 1 : Architecture de MongoDB montrant les relations entre les différents composants.

      2. Pourquoi choisir MongoDB ?

        1. Performance

          Moteur de stockage haute performance avec :

          Exemple de performance

          Un site e-commerce utilisant MongoDB peut gérer jusqu'à 100 000 lectures par seconde avec des temps de réponse inférieurs à 10ms, ce qui permet une expérience utilisateur fluide même pendant les périodes de pointe comme le Black Friday.

          • Support natif de la réplication
          • Sharding intégré
          • Indexation avancée
          • Cache de requêtes
        2. Scalabilité

          Architecture distribuée conçue pour :

          Exemple de scalabilité

          Une application de médias sociaux peut commencer avec un seul serveur MongoDB. À mesure que le nombre d'utilisateurs passe de 1 000 à 10 millions, l'application peut évoluer en ajoutant des shards (partitions de données) sur plusieurs serveurs, sans temps d'arrêt.

          • Échelle horizontale facile
          • Répartition des charges
          • Haute disponibilité
        3. Modèle de données flexible

          Avantages du schéma dynamique :

          Exemple de flexibilité

          Dans une application de blog, vous pourriez initialement stocker uniquement le titre et le contenu d'un article. Plus tard, vous pourriez ajouter des champs comme des tags, une image de couverture ou des commentaires directement dans le même document, sans avoir à modifier la structure de la base de données.

          ```
          // Premier enregistrement
          {
            titre: "Mon premier article",
            contenu: "Contenu de l'article...",
            date: ISODate("2023-01-01")
          }
          
          // Plus tard, ajout de nouveaux champs sans modification de schéma
          {
            titre: "Nouvel article",
            contenu: "Contenu mis à jour...",
            date: ISODate("2023-04-15"),
            tags: ["technologie", "programmation"],
            image: "url-de-l-image.jpg",
            auteur: {
              nom: "Alice",
              role: "rédacteur"
            },
            commentaires: [
              { auteur: "Bob", texte: "Super article !", date: ISODate("2023-04-16") }
            ]
          }
          ```
          
          • Évolution sans temps d'arrêt
          • Documents hétérogènes
          • Modélisation naturelle des données
        4. Écosystème riche

          Une large gamme d'outils :

          Exemples d'outils populaires

          • MongoDB Compass : Interface graphique pour explorer et manipuler les données
          • MongoDB Atlas : Service cloud géré avec hébergement sur AWS, Azure ou GCP
          • MongoDB Charts : Outil de visualisation de données intégré
          • MongoDB BI Connector : Permet d'utiliser des outils BI comme Tableau avec MongoDB
          • Drivers officiels : Pour Node.js, Python, Java, C#, etc.

          Astuce : Ces outils rendent MongoDB accessible aussi bien aux développeurs qu'aux analystes de données, facilitant ainsi la collaboration entre les équipes.

          • Drivers pour tous les langages majeurs
          • Outils de gestion (Compass, Atlas)
          • Intégrations cloud
          • Communauté active
      3. Concepts clés du NoSQL

        1. Modèles de données NoSQL

          • Document

            Stockage de documents JSON/BSON

            Ex: MongoDB, CouchDB

          • Clé-Valeur

            Stockage simple clé-valeur

            Ex: Redis, DynamoDB

          • Colonnes larges

            Stockage par colonnes

            Ex: Cassandra, HBase

          • Graphes

            Relations complexes entre données

            Ex: Neo4j, ArangoDB

        2. ACID vs BASE

          ACID (SQL) BASE (NoSQL) Description
          Atomicité Disponibilité de base Disponibilité même en cas de pannes
          Cohérence État souple (Soft state) Les données peuvent évoluer sans mise à jour
          Isolation Cohérence à terme Les données finissent par être cohérentes
          Durabilité Scalabilité horizontale Capacité à gérer de grandes quantités de données
      4. Quand utiliser MongoDB ?

        Idéal pour
        • Applications web et mobiles API RESTful
        • Gestion de contenu (CMS) Contenu dynamique
        • Catalogues produits E-commerce
        • Données IoT et séries temporelles Big Data
        • Profils utilisateurs Données utilisateurs
        • Données géospatiales Géolocalisation
        Moins adapté pour
        • Applications financières Transactions complexes
        • Systèmes relationnels Jointures complexes
        • Applications critiques Cohérence forte requise
        • Requêtes complexes SQL avancé
        • Données hautement relationnelles Modèle relationnel
        Conseil :

        MongoDB excelle dans les cas d'utilisation nécessitant flexibilité et évolutivité. Pour les systèmes transactionnels complexes, envisagez une base de données relationnelle traditionnelle.

      5. Opérations CRUD avec MongoDB

        Les opérations CRUD (Create, Read, Update, Delete) sont fondamentales pour interagir avec une base de données MongoDB. Voici comment les mettre en œuvre :

        1. Create - Insertion de documents

          Pour insérer des documents dans une collection :

                              // Insérer un seul document
                                db.collection('users').insertOne({
                                  name: 'Jean Dupont',
                                  email: 'jean@exemple.com',
                                  age: 30,
                                  status: 'actif'
                                });
          
                                // Insérer plusieurs documents
                                db.collection('posts').insertMany([
                                  { title: 'Premier article', content: 'Contenu...', likes: 0 },
                                  { title: 'Deuxième article', content: 'Contenu...', tags: ['tech', 'mongodb'] }
                                ]);
                              
                            
          MongoDB génère automatiquement un _id unique pour chaque document si aucun n'est spécifié.
        2. Read - Lecture de documents

          Pour rechercher des documents :

                              // Trouver tous les documents
                                  db.collection('users').find({});
          
                                  // Avec des critères de recherche
                                  db.collection('users').find({ status: 'actif' });
          
                                  // Avec projection (sélection des champs)
                                  db.collection('users').find(
                                    { age: { $gt: 25 } },
                                    { projection: { name: 1, email: 1, _id: 0 } }
                                  );
          
                                  // Trier et limiter les résultats
                                  db.collection('posts')
                                    .find({})
                                    .sort({ created_at: -1 })
                                    .limit(10);
                                
                            
        3. Update - Mise à jour de documents

          Pour mettre à jour des documents :

                              // Mettre à jour un seul document
                                db.collection('users').updateOne(
                                  { email: 'jean@exemple.com' },
                                  { $set: { status: 'inactif' } }
                                );
          
                                // Mettre à jour plusieurs documents
                                db.collection('posts').updateMany(
                                  { views: { $lt: 100 } },
                                  { $inc: { views: 1 } }
                                );
          
                                // Opérateurs de mise à jour courants :
                                // $set, $unset, $inc, $push, $pull, $addToSet
                              
                            
        4. Delete - Suppression de documents

          Pour supprimer des documents :

                              // Supprimer un seul document
                                db.collection('users').deleteOne({ email: 'jean@exemple.com' });
          
                                // Supprimer plusieurs documents
                                db.collection('posts').deleteMany({ status: 'archived' });
          
                                // Attention : Sans filtre, cela supprime tous les documents de la collection !
                                // db.collection('users').deleteMany({});
                              
                            
          Attention : Les opérations de suppression sont irréversibles. Toujours vérifier ses critères de sélection avant de supprimer.
        5. Bonnes pratiques CRUD

          • Utilisez des index pour optimiser les requêtes de lecture
          • Privilégiez les opérations en masse (insertMany, updateMany) pour améliorer les performances
          • Utilisez les transactions pour les opérations atomiques sur plusieurs documents
          • Limitez les champs retournés avec la projection pour réduire la charge réseau
          • Pensez à la cohérence des données dans un environnement distribué
    2. Structure des documents MongoDB

      1. Introduction au format BSON

        MongoDB utilise le format BSON (Binary JSON) pour stocker les documents. C'est une représentation binaire de JSON avec des types de données supplémentaires.

        Avantages du BSON :

        1. Plus rapide à analyser que JSON
        2. Supporte plus de types de données
        3. Efficace pour le stockage et la récupération
      2. Anatomie d'un document

        Un document MongoDB typique :

        {
          _id: ObjectId("507f1f77bcf86cd799439011"),
          nom: "Jean Dupont",
          age: 30,
          email: "jean.dupont@example.com",
          adresse: {
            rue: "123 Rue Exemple",
            ville: "Paris",
            codePostal: "75000"
          },
          competences: ["MongoDB", "JavaScript", "Node.js"],
          dateInscription: ISODate("2023-01-15T10:30:00Z")
        }
      3. Types de données

        1. Types scalaires
          1. String : Chaînes de caractères UTF-8
          2. Number : Entiers, décimaux, doubles
          3. Boolean : true/false
          4. Date : Horodatage
          5. Null : Valeur nulle
        2. Types composés
          1. Document : Objet imbriqué
          2. Array : Tableau de valeurs
        3. Types spéciaux
          1. ObjectId : Identifiant unique
          2. Binary Data : Données binaires
          3. Regular Expression : Expressions régulières
          4. Timestamp : Horodatage interne
      4. Bonnes pratiques de modélisation

        1. Conception orientée documents

          Regrouper les données fréquemment accédées ensemble

        2. Éviter les jointures excessives

          Privilégier l'imbrication quand c'est pertinent

        3. Utilisation des références

          Pour les relations un-à-plusieurs ou plusieurs-à-plusieurs

        4. Considérations sur la taille des documents

          Éviter les documents trop volumineux (>16Mo)

    3. Guide Complet des Opérations MongoDB

      Ce guide couvre en détail les opérations CRUD (Create, Read, Update, Delete) dans MongoDB.

      Recherche de Documents (find)

      1. Syntaxe de Base

            
                // Syntaxe de base de la méthode find()
                // db.collection.find(query, projection)
        
                // Exemple 1: Trouver tous les documents
                const allDocuments = db.users.find({});
        
                // Exemple 2: Trouver avec des critères de recherche
                const activeUsers = db.users.find({
                    status: 'active',
                    lastLogin: { $gt: new Date('2023-01-01') }
                });
        
                // Exemple 3: Utilisation de la projection
                const userNames = db.users.find(
                    { role: 'user' },
                    { 
                        name: 1, 
                        email: 1,
                        _id: 0  // Exclure le champ _id
                    }
                );
        
                // Exemple 4: Trier et limiter les résultats
                const recentOrders = db.orders
                    .find({ status: 'completed' })
                    .sort({ orderDate: -1 })
                    .limit(10);
        
                // Exemple 5: Compter les documents
                const activeUserCount = db.users.countDocuments({ status: 'active' });
        
                // Exemple 6: Utilisation d'opérateurs de requête
                const highValueOrders = db.orders.find({
                    total: { $gt: 1000 },  // Montant supérieur à 1000
                    status: { $in: ['pending', 'processing'] },  // Statut dans la liste
                    orderDate: { 
                        $gte: new Date('2023-01-01'),
                        $lt: new Date('2024-01-01')
                    }
                });
        
                // Exemple 7: Recherche avec expression régulière
                const nameStartsWithJ = db.users.find({
                    name: { $regex: /^J/i }  // Noms commençant par J (insensible à la casse)
                });
        
                // Exemple 8: Requête sur des tableaux
                const usersWithSpecificTags = db.users.find({
                    tags: { $all: ['premium', 'verified'] }  // Doit avoir tous les tags spécifiés
                });
        
                // Exemple 9: Requête avec opérateurs logiques
                const complexQuery = db.products.find({
                    $or: [
                        { category: 'electronics', price: { $lt: 500 } },
                        { category: 'books', rating: { $gte: 4 } }
                    ],
                    inStock: true
                });
        
                // Exemple 10: Utilisation de $elemMatch pour les tableaux d'objets
                const usersWithSpecificAddress = db.users.find({
                    addresses: {
                        $elemMatch: {
                            type: 'billing',
                            city: 'Paris'
                        }
                    }
                });
            
        
      2. Exemple Simple

            
              // Trouver tous les utilisateurs actifs
              db.users.find({ 
                  status: 'active',
                  lastLogin: { $gt: new Date('2023-01-01') }
              }).sort({ createdAt: -1 });
            
        
      3. Avec Projection

            
                // Sélectionner uniquement certains champs
                db.users.find(
                { role: 'customer' },
                { 
                    name: 1, 
                    email: 1, 
                    _id: 0  // Exclure le champ _id
                }
                ).limit(10);
            
        
      4. Opérateurs de Requête Courants

        Opérateur Description Exemple
        $eq Égal à { age: { $eq: 25 } }
        $gt, $gte Plus grand (ou égal) que { age: { $gt: 21 } }
        $in, $nin Dans / pas dans un tableau { role: { $in: ["admin", "editor"] } }
        $and, $or Opérateurs logiques { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] }
      5. Bonnes Pratiques

        • Utilisez des index pour améliorer les performances
        • Limitez les champs retournés avec la projection
        • Évitez les opérations qui scannent toute la collection (COLLSCAN)
        • Utilisez .explain() pour analyser les performances des requêtes
      1. Les Commandes d'Insertion

        1. Méthodes Disponibles

          1. insertOne()

            Insère un seul document
            // Insérer un seul document
            const result = await db.users.insertOne({
              name: "Jean Dupont",
              email: "jean@example.com",
              age: 30,
              roles: ["user", "admin"],
              createdAt: new Date()
            });
            
            console.log(`Document inséré avec l'ID: ${result.insertedId}`);
            
            // Résultat attendu :
            // Document inséré avec l'ID: 5f8d... (ObjectId)
          2. insertMany()

            Insère plusieurs documents
            // Insérer plusieurs documents
            const result = await db.products.insertMany([
              {
                name: "Ordinateur portable",
                category: "Électronique",
                price: 999.99,
                inStock: true,
                tags: ["nouveau", "promo"]
              },
              {
                name: "Souris sans fil",
                category: "Périphériques",
                price: 49.99,
                inStock: true
              },
              {
                name: "Clavier mécanique",
                category: "Périphériques",
                price: 89.99,
                inStock: false
              }
            ], {
              writeConcern: { w: "majority" },
              ordered: true  // Annule l'insertion en cas d'erreur
            });
            
            console.log(`${result.insertedCount} documents insérés`);
            console.log("IDs des documents insérés:", result.insertedIds);
            
            // Résultat attendu :
            // 3 documents insérés
            // IDs des documents insérés: {
            //   '0': ObjectId("..."),
            //   '1': ObjectId("..."),
            //   '2': ObjectId("...")
            // }
        2. Options d'Insertion

          Option Type Description Valeur par défaut
          writeConcern Document Niveau de garantie d'écriture { w: 1 }
          ordered Boolean Arrêter à la première erreur si false true
          bypassDocumentValidation Boolean Contourner la validation du schéma false
        3. Bonnes Pratiques

          • Utilisez insertMany() pour insérer plusieurs documents en une seule opération
          • Désactivez ordered pour ignorer les erreurs et continuer l'insertion
          • Validez les données avant l'insertion
          • Utilisez des transactions pour des opérations atomiques sur plusieurs collections
        4. Génération des _id

          Si non spécifié, MongoDB génère un _id unique de type ObjectId :

                              
                                {
                                    _id: ObjectId("507f1f77bcf86cd799439011"),  // Format 12-byte
                                    // 4 bytes: timestamp
                                    // 5 bytes: random value
                                    // 3 bytes: counter
                                    ...
                                  }
                                
                            

          Pour utiliser un identifiant personnalisé :

          // Insérer un seul document
          const result = await db.users.insertOne({
            name: "Jean Dupont",
            email: "jean@example.com",
            age: 30,
            roles: ["user", "admin"],
            createdAt: new Date()
          });
          
          console.log(`Document inséré avec l'ID: ${result.insertedId}`);
          
          // Résultat attendu :
          // Document inséré avec l'ID: 5f8d... (ObjectId)
      2. Les Commandes de Mise à Jour

        1. Méthodes Principales

          1. updateOne()

            Met à jour un seul document
            // Mettre à jour un document spécifique
            const result = await db.products.updateOne(
              { _id: ObjectId("507f1f77bcf86cd799439011") },  // Filtre
              {
                $set: {  // Opérateur de mise à jour
                  price: 1099.99,
                  lastModified: new Date()
                },
                $inc: { viewCount: 1 },
                $addToSet: { tags: "nouveau" }
              },
              {
                upsert: false,  // Ne pas créer le document s'il n'existe pas
                writeConcern: { w: "majority" }
              }
            );
            
            console.log(`${result.matchedCount} document(s) correspondant(s)`);
            console.log(`${result.modifiedCount} document(s) modifié(s)`);
            console.log(`ID du document inséré: ${result.upsertedId || 'Aucun'}`);
            
            // Résultat attendu :
            // 1 document(s) correspondant(s)
            // 1 document(s) modifié(s)
            // ID du document inséré: Aucun
          2. updateMany()

            Met à jour plusieurs documents
            // Mettre à jour plusieurs documents correspondant aux critères
            const result = await db.products.updateMany(
              { 
                category: "Électronique",
                price: { $lt: 1000 }  // Produits électroniques à moins de 1000€
              },
              {
                $set: { 
                  onSale: true,
                  discount: 0.1,  // 10% de réduction
                  lastPromoUpdate: new Date()
                },
                $inc: { price: 50 }  // Augmenter le prix de 50€
              },
              {
                writeConcern: { w: "majority" },
                upsert: false
              }
            );
            
            console.log(`${result.matchedCount} document(s) correspondant(s)`);
            console.log(`${result.modifiedCount} document(s) modifié(s)`);
            console.log(`ID du document inséré: ${result.upsertedId || 'Aucun'}`);
            
            // Résultat attendu (exemple) :
            // 15 document(s) correspondant(s)
            // 15 document(s) modifié(s)
            // ID du document inséré: Aucun
        2. Opérateurs de Mise à Jour

          1. Opérateurs de Champs
            • $set : Définit la valeur d'un champ
            • $unset : Supprime un champ
            • $rename : Renomme un champ
            • $inc : Incrémente une valeur numérique
            • $mul : Multiplie une valeur numérique
            • $min/$max : Met à jour si la valeur est plus petite/plus grande
          2. Opérateurs de Tableaux
            • $push : Ajoute un élément à un tableau
            • $addToSet : Ajoute si non présent
            • $pop : Supprime le premier/dernier élément
            • $pull : Supprime les éléments correspondants
            • $pullAll : Supprime plusieurs valeurs
            • $each : Utilisé avec $push et $addToSet pour ajouter plusieurs éléments
          3. Exemple Complet avec Opérateurs

                                                // Mettre à jour un profil utilisateur complexe
                                                    await db.users.updateOne(
                                                        { _id: userId },
                                                        {
                                                        $set: {
                                                            "profile.lastUpdated": new Date(),
                                                            "contact.email": "new.email@example.com",
                                                            "settings.theme": "dark"
                                                        },
                                                        $inc: { "stats.profileViews": 1 },
                                                        $addToSet: { 
                                                            tags: { $each: ["premium", "verified"] } 
                                                        },
                                                        $pull: { 
                                                            notifications: { 
                                                            type: "promo",
                                                            status: "unread" 
                                                            } 
                                                        }
                                                        },
                                                        { 
                                                        upsert: true,  // Crée le document s'il n'existe pas
                                                        writeConcern: { w: "majority" }
                                                        }
                                                    );
                                                
                                            
        3. Pièges Courants

          • Les mises à jour atomiques ne sont pas garanties sans _id dans le filtre
          • Les opérations de mise à jour sont atomiques au niveau du document
          • Les index peuvent affecter les performances des mises à jour
          • Les validations de schéma s'appliquent aux mises à jour
        4. Mise à Jour avec Agrégation (MongoDB 4.2+)

          Permet des mises à jour complexes en utilisant le pipeline d'agrégation :

                                      // Mettre à jour en fonction des valeurs existantes
                                          await db.orders.updateMany
                                          (
                                              { status: "processing" },
                                              [
                                              {
                                                  $set: {
                                                  lastUpdated: "$$NOW",
                                                  total: {
                                                      $add: [
                                                      "$subtotal",
                                                      { $multiply: ["$subtotal", "$taxRate"] },
                                                      "$shipping"
                                                      ]
                                                  }
                                                  }
                                              },
                                              {
                                                  $unset: ["tempField1", "tempField2"]
                                              }
                                          ]
                                          );
                                      
                                  
      3. Suppression de Documents

        Attention : Les opérations de suppression sont irréversibles. Utilisez ces commandes avec précaution.
        1. deleteOne()

          Suppression d'un document
          // Supprimer un document spécifique
          const result = await db.users.deleteOne(
            { _id: ObjectId("507f1f77bcf86cd799439011") },  // Filtre
            {
              writeConcern: { w: "majority" },
              collation: { locale: "fr", strength: 1 }  // Optionnel : pour la sensibilité à la casse
            }
          );
          
          console.log(`${result.deletedCount} document(s) supprimé(s)`);
          
          // Exemple avec journalisation avant suppression
          try {
            const user = await db.users.findOne({ _id: ObjectId("507f1f77bcf86cd799439011") });
            if (user) {
              await db.deletedUsers.insertOne({
                ...user,
                deletedAt: new Date(),
                deletedBy: "admin@example.com"
              });
              
              const result = await db.users.deleteOne({ _id: user._id });
              console.log(`Utilisateur ${user.email} supprimé avec succès`);
            }
          } catch (error) {
            console.error("Erreur lors de la suppression:", error);
          }
          
          // Résultat attendu (exemple) :
          // 1 document(s) supprimé(s)
          // OU
          // Utilisateur test@example.com supprimé avec succès
        2. deleteMany()

          Suppression de plusieurs documents Télécharger
          // Supprimer plusieurs documents correspondant aux critères
          const result = await db.logs.deleteMany(
            { 
              // Supprimer les logs plus anciens que 30 jours
              timestamp: { 
                $lt: new Date(new Date() - 30 * 24 * 60 * 60 * 1000)
              },
              // Ne pas supprimer les logs importants
              priority: { $ne: "high" }
            },
            {
              writeConcern: { 
                w: "majority",
                wtimeout: 5000  // Timeout de 5 secondes
              },
              comment: "Nettoyage des logs mensuel"  // Pour le suivi des opérations
            }
          );
          
          console.log(`${result.deletedCount} logs supprimés`);
          
          // Exemple avec journalisation avancée
          const batchSize = 1000;
          let deletedCount = 0;
          let lastId = null;
          
          while (true) {
            // Récupérer un lot de documents à supprimer
            const batch = await db.logs
              .find(lastId ? { 
                _id: { $gt: lastId },
                timestamp: { $lt: new Date(new Date() - 30 * 24 * 60 * 60 * 1000) }
              } : { 
                timestamp: { $lt: new Date(new Date() - 30 * 24 * 60 * 60 * 1000) }
              })
              .sort({ _id: 1 })
              .limit(batchSize)
              .toArray();
          
            if (batch.length === 0) break;
            
            // Récupérer les IDs à supprimer
            const idsToDelete = batch.map(doc => doc._id);
            
            // Journaliser avant suppression
            await db.deletedLogs.insertMany(batch.map(doc => ({
              ...doc,
              deletedAt: new Date(),
              deletedBy: "cleanup-script"
            })));
            
            // Supprimer le lot
            const result = await db.logs.deleteMany({ _id: { $in: idsToDelete } });
            deletedCount += result.deletedCount;
            
            // Mettre à jour le dernier ID traité
            lastId = batch[batch.length - 1]._id;
            
            console.log(`Lot de ${result.deletedCount} logs supprimés (total: ${deletedCount})`);
            
            // Pause pour réduire la charge sur le serveur
            await new Promise(resolve => setTimeout(resolve, 100));
          }
          
          console.log(`Opération terminée. Total supprimé: ${deletedCount} logs.`);
          
          // Résultat attendu (exemple) :
          // Lot de 1000 logs supprimés (total: 1000)
          // Lot de 1000 logs supprimés (total: 2000)
          // Lot de 345 logs supprimés (total: 2345)
          // Opération terminée. Total supprimé: 2345 logs.
        3. Bonnes Pratiques

          • Toujours sauvegarder les données avant des suppressions en masse
          • Utiliser des transactions pour des suppressions atomiques sur plusieurs collections
          • Envisagez d'utiliser des "suppressions logiques" (champ "deleted") plutôt que des suppressions physiques
          • Testez toujours les critères de suppression avec une requête find() d'abord
      4. Requêtes Avancées MongoDB

        Cette section couvre des requêtes complexes combinant plusieurs opérateurs et étapes d'agrégation.
        1. Jointures Complexes avec $lookup et $unwind

          Scénario :

          Récupérer les commandes avec les détails des produits et les informations clients, en calculant le total par catégorie.

              
                  db.orders.aggregate([
            // Étape 1: Filtrer les commandes des 30 derniers jours
            {
              $match: {
                orderDate: { $gte: new Date(new Date() - 30 * 24 * 60 * 60 * 1000) }
              }
            },
            
            // Étape 2: Joindre avec la collection des clients
            {
              $lookup: {
                from: "customers",
                localField: "customerId",
                foreignField: "_id",
                as: "customer"
              }
            },
            
            // Étape 3: Déplier le tableau des articles commandés
            { $unwind: "$items" },
            
            // Étape 4: Joindre avec la collection des produits
            {
              $lookup: {
                from: "products",
                localField: "items.productId",
                foreignField: "_id",
                as: "product"
              }
            },
            
            // Étape 5: Déplier le tableau des produits
            { $unwind: "$product" },
            
            // Étape 6: Calculer le total pour chaque ligne de commande
            {
              $addFields: {
                "items.total": { $multiply: ["$items.quantity", "$product.price"] }
              }
            },
            
            // Étape 7: Grouper par catégorie de produit et calculer les totaux
            {
              $group: {
                _id: { category: "$product.category" },
                totalSales: { $sum: "$items.total" },
                orderCount: { $sum: 1 },
                averageOrderValue: { $avg: "$items.total" }
              }
            },
            
            // Étape 8: Trier par total des ventes (décroissant)
            { $sort: { totalSales: -1 } }
          ])
              
          

          Explication :

          1. $match : Filtre les commandes récentes
          2. $lookup : Jointure avec la collection des clients
          3. $unwind : Déploie le tableau des articles
          4. $lookup : Jointure avec la collection des produits
          5. $group : Agrège par catégorie avec calculs
          6. $project : Formate le résultat final
        2. Requêtes Géospatiales Avancées

          Scénario :

          Trouver les 10 restaurants les plus proches dans un rayon de 2 km, avec une note moyenne supérieure à 4.

          Recherche géospatiale avec agrégation
          // 1. Création d'un index géospatial 2dsphere (à exécuter une seule fois)
          // db.restaurants.createIndex({ location: "2dsphere" });
          
          // 2. Requête pour trouver les restaurants à proximité
          const pointInteret = {
            type: "Point",
            coordinates: [2.3522, 48.8566]  // Paris, France
          };
          
          const result = await db.restaurants.aggregate([
            {
              $geoNear: {
                near: pointInteret,
                distanceField: "distance",
                maxDistance: 2000,  // 2 km en mètres
                spherical: true,
                query: { 
                  'grades.score': { $gte: 4 },
                  cuisine: { $exists: true }
                }
              }
            },
            {
              $lookup: {
                from: "neighborhoods",
                localField: "neighborhood",
                foreignField: "name",
                as: "neighborhood_info"
              }
            },
            { $unwind: "$neighborhood_info" },
            {
              $project: {
                name: 1,
                cuisine: 1,
                "address.street": 1,
                distance: { $round: ["$distance", 0] },
                neighborhood: "$neighborhood_info.name",
                borough: 1,
                lastGrade: { $arrayElemAt: ["$grades", -1] }
              }
            },
            { $sort: { distance: 1 } },
            { $limit: 10 }
          ]);
          
          console.log(JSON.stringify(result, null, 2));
        3. Recherche de Texte Avancée

          Scénario :

          Recherche avancée d'articles de blog avec pondération des champs, filtrage par date, catégorie et popularité.

          Recherche de texte avancée avec agrégation
          // 1. Création d'un index de recherche en texte (à exécuter une seule fois)
          // db.articles.createIndex(
          //   { 
          //     title: "text", 
          //     content: "text",
          //     tags: "text"
          //   },
          //   {
          //     weights: {
          //       title: 5,    // Le titre a plus de poids
          //       tags: 3,     // Les tags ont un poids moyen
          //       content: 1   // Le contenu a le poids le plus faible
          //     },
          //     name: "text_search_index"
          //   }
          // );
          
          // 2. Requête de recherche avancée avec agrégation
          const searchTerm = "développement web";
          const minDate = new Date(new Date().setFullYear(new Date().getFullYear() - 1)); // Dernière année
          
          const result = await db.articles.aggregate([
            {
              $search: {
                text: {
                  query: searchTerm,
                  path: ["title", "content", "tags"],
                  fuzzy: {
                    maxEdits: 2,        // Tolère jusqu'à 2 fautes de frappe
                    prefixLength: 3,    // Nécessite les 3 premières lettres exactes
                    maxExpansions: 100  // Limite l'expansion des termes
                  },
                  score: { 
                    // Boost pour les correspondances exactes
                    boost: { value: 2 }
                  }
                },
                // Filtres supplémentaires
                compound: {
                  filter: [
                    { 
                      range: {
                        path: "publishedAt",
                        gte: minDate,
                        lte: new Date()
                      }
                    },
                    { 
                      range: {
                        path: "readTime",
                        lte: 15  // Temps de lecture max de 15 minutes
                      }
                    },
                    { 
                      text: {
                        query: ["tutoriel", "guide", "exemple"],
                        path: "tags"
                      }
                    }
                  ],
                  // Boost pour les articles populaires
                  should: [
                    {
                      range: {
                        path: "views",
                        boost: {
                          linear: {
                            origin: 0,
                            scale: 10000,
                            decay: 0.5
                          }
                        }
                      }
                    },
                    {
                      range: {
                        path: "claps",
                        boost: {
                          linear: {
                            origin: 0,
                            scale: 1000,
                            decay: 0.5
                          }
                        }
                      }
                    }
                  ]
                }
              }
            },
            // Jointure avec la collection des auteurs
            {
              $lookup: {
                from: "users",
                localField: "authorId",
                foreignField: "_id",
                as: "author"
              }
            },
            { $unwind: "$author" },
            // Projection des champs pertinents
            {
              $project: {
                _id: 1,
                title: 1,
                excerpt: 1,
                readTime: 1,
                publishedAt: 1,
                views: 1,
                claps: 1,
                tags: 1,
                author: {
                  name: 1,
                  avatar: 1,
                  title: 1
                },
                // Calcul du score de pertinence
                relevance: {
                  $meta: "searchScore"
                },
                // Calcul d'un score personnalisé
                score: {
                  $add: [
                    { $multiply: [{ $meta: "searchScore" }, 0.6] },
                    { $multiply: [{ $divide: ["$views", 1000] }, 0.2] },
                    { $multiply: [{ $divide: ["$claps", 100] }, 0.2] }
                  ]
                }
              }
            },
            // Tri par score personnalisé
            { $sort: { score: -1 } },
            // Pagination
            { $skip: 0 },
            { $limit: 10 }
          ]);
          
          console.log(JSON.stringify(result, null, 2));
        4. Agrégations Temporelles

          Scénario :

          Analyser les ventes par période (jour, semaine, mois) avec des fenêtres glissantes.

          Agrégation de séries temporelles avancée
          // 1. Création d'une collection de séries temporelles (à exécuter une seule fois)
          // db.createCollection("sensorReadings", {
          //   timeseries: {
          //     timeField: "timestamp",
          //     metaField: "sensorId",
          //     granularity: "minutes"
          //   }
          // });
          
          // 2. Agrégation avancée sur les séries temporelles
          const startDate = new Date();
          startDate.setMonth(startDate.getMonth() - 6); // Données des 6 derniers mois
          
          const result = await db.sensorReadings.aggregate([
            // Étape 1: Filtrer par plage de dates
            {
              $match: {
                timestamp: { $gte: startDate },
                status: "active"
              }
            },
            
            // Étape 2: Grouper par fenêtres de temps et capteur
            {
              $group: {
                _id: {
                  // Arrondir à l'heure la plus proche
                  date: {
                    $dateTrunc: {
                      date: "$timestamp",
                      unit: "hour",
                      binSize: 1
                    }
                  },
                  sensorId: "$sensorId",
                  location: "$location"
                },
                // Calculer les métriques
                avgValue: { $avg: "$value" },
                maxValue: { $max: "$value" },
                minValue: { $min: "$value" },
                sampleCount: { $sum: 1 },
                // Détecter les anomalies (valeurs en dehors de 2 écarts-types)
                stdDev: { $stdDevSamp: "$value" },
                // Garder le premier et dernier timestamp de la fenêtre
                firstTimestamp: { $first: "$timestamp" },
                lastTimestamp: { $last: "$timestamp" },
                // Collecter les 5 premières valeurs pour référence
                sampleValues: { $push: { $slice: ["$value", 5] } }
              }
            },
            
            // Étape 3: Calculer les anomalies
            {
              $addFields: {
                isAnomaly: {
                  $or: [
                    { 
                      $gt: [
                        "$maxValue",
                        { $add: ["$avgValue", { $multiply: [2, "$stdDev"] }] }
                      ]
                    },
                    { 
                      $lt: [
                        "$minValue",
                        { $subtract: ["$avgValue", { $multiply: [2, "$stdDev"] }] }
                      ]
                    }
                  ]
                },
                // Calculer la tendance sur la fenêtre
                valueChange: {
                  $subtract: [
                    { $arrayElemAt: ["$sampleValues", -1] },
                    { $arrayElemAt: ["$sampleValues", 0] }
                  ]
                }
              }
            },
            
            // Étape 4: Projeter les champs pertinents
            {
              $project: {
                _id: 0,
                timestamp: "$_id.date",
                sensorId: "$_id.sensorId",
                location: "$_id.location",
                metrics: {
                  average: { $round: ["$avgValue", 2] },
                  max: { $round: ["$maxValue", 2] },
                  min: { $round: ["$minValue", 2] },
                  sampleCount: 1,
                  standardDeviation: { $round: ["$stdDev", 2] },
                  isAnomaly: 1,
                  valueChange: { $round: ["$valueChange", 2] },
                  timeRange: {
                    start: "$firstTimestamp",
                    end: "$lastTimestamp"
                  }
                }
              }
            },
            
            // Étape 5: Trier par date et capteur
            {
              $sort: {
                timestamp: 1,
                sensorId: 1
              }
            },
            
            // Étape 6: Optionnel - Fenêtres mobiles
            {
              $setWindowFields: {
                partitionBy: "$sensorId",
                sortBy: { timestamp: 1 },
                output: {
                  movingAvg: {
                    $avg: "$metrics.average",
                    window: {
                      documents: ["unbounded", "current"]
                    }
                  },
                  movingStdDev: {
                    $stdDevSamp: "$metrics.average",
                    window: {
                      documents: ["unbounded", "current"]
                    }
                  }
                }
              }
            }
          ]);
          
          console.log(JSON.stringify(result, null, 2));
    4. Indexation

      Types d'index

      • Index simple : Sur un champ unique
      • Index composé : Sur plusieurs champs
      • Index textuel : Pour les recherches textuelles
      • Index géospatial : Pour les données de localisation

      Création d'un index

      // 1. Création d'un index simple sur un champ unique
      // Crée un index croissant (1) sur le champ 'email'
      db.utilisateurs.createIndex({ email: 1 });
      
      // 2. Création d'un index composé sur plusieurs champs
      db.commandes.createIndex({ clientId: 1, date: -1 });
      // - clientId en ordre croissant
      // - date en ordre décroissant (pour avoir les commandes les plus récentes en premier)
      
      // 3. Création d'un index unique avec contrainte
      db.utilisateurs.createIndex(
        { username: 1 },
        { unique: true, name: "username_unique" }
      );
      
      // 4. Création d'un index TTL (Time-To-Live) pour l'expiration automatique des documents
      db.sessions.createIndex(
        { lastActivity: 1 },
        { expireAfterSeconds: 3600 * 24 * 7 } // Supprime après 7 jours d'inactivité
      );
      
      // 5. Création d'un index de texte pour la recherche plein texte
      db.articles.createIndex(
        { titre: "text", contenu: "text" },
        { weights: { titre: 3, contenu: 1 } } // Le titre a plus de poids que le contenu
      );
      
      // 6. Création d'un index géospatial 2dsphere pour les requêtes géographiques
      db.restaurants.createIndex({ localisation: "2dsphere" });
      
      // 7. Création d'un index partiel (seulement sur les documents qui correspondent au filtre)
      db.articles.createIndex(
        { vues: 1 },
        { partialFilterExpression: { etat: "publié" } }
      );
      
      // 8. Création d'un index avec options avancées
      db.produits.createIndex(
        { nom: 1, categorie: 1 },
        {
          name: "idx_nom_categorie",
          background: true,        // Construction en arrière-plan
          sparse: true,            // N'inclut que les documents où le champ existe
          collation: {             // Règles de tri spécifiques
            locale: "fr",
            strength: 2
          }
        }
      );
      
      // Vérification des index existants sur une collection
      db.utilisateurs.getIndexes();
      
      // Suppression d'un index
      db.utilisateurs.dropIndex("email_1");
      
      // Suppression de tous les index (sauf _id)
      // db.utilisateurs.dropIndexes();

      Meilleures pratiques

      • Indexer les champs fréquemment utilisés
      • Éviter les index trop complexes
      • Surveiller l'utilisation des index
      • Supprimer les index inutilisés
    5. Aggregation Pipeline

      Opérateurs principaux

      • $match : Filtrage des documents
      • $group : Agrégation de données
      • $sort : Tri des résultats
      • $project : Sélection des champs
      • $limit : Limite des résultats

      Exemple d'aggregation

      db.collection.aggregate([
        { $match: { age: { $gt: 25 } } },
        { $group: {
            _id: "$city",
            averageAge: { $avg: "$age" }
          }
        },
        { $sort: { averageAge: -1 } },
        { $limit: 5 }
      ]);
      
    6. Best Practices

      Performance

      • Utiliser des index appropriés
      • Optimiser les requêtes
      • Éviter les documents trop volumineux
      • Utiliser les projections

      Structure des données

      • Choisir une structure adaptée
      • Gérer les relations entre documents
      • Éviter les redondances inutiles
      • Documenter la structure

      Sécurité

      • Utiliser des schémas sécurisés
      • Restreindre les accès
      • Utiliser l'authentification
      • Activer l'encryption
    7. Quiz

      Quelles sont les principales opérations CRUD en MongoDB ?
    8. QCM

  6. MongoDB pour le Big Data

    1. Scalabilité et haute disponibilité

      1. Sharding : partitionnement horizontal pour les bases de données massives
        Note : Le sharding permet de répartir les données sur plusieurs serveurs pour absorber de très gros volumes.
      2. Réplication : configuration d'un Replica Set pour la tolérance aux pannes
        Note : Un Replica Set assure la haute disponibilité et la reprise automatique en cas de panne d'un serveur.
      3. Indexation : optimisation des requêtes (createIndex, types d'index, compound indexes)
        Note : Bien choisir ses index est crucial pour les performances sur de gros volumes.
    2. Intégration avec des outils Big Data

      1. Connecteurs MongoDB pour Hadoop et Spark
        Exemple : Utilisez le MongoDB Connector for Spark pour analyser de grandes quantités de données.
      2. Utilisation avec Kafka pour le streaming de données
        Note : Le Kafka Connector permet d'intégrer MongoDB dans des architectures temps réel.
      3. Utilisation comme stockage pour les pipelines ETL
        MongoDB est souvent utilisé comme zone de transit ou de stockage intermédiaire dans les workflows Big Data.
    3. Cas d'usage Big Data

      1. Stockage de logs applicatifs massifs
      2. Analyse de données IoT à grande échelle
      3. Reporting et BI sur de très gros volumes
    4. Quiz

      Quelles sont les deux principales stratégies pour gérer de très gros volumes de données dans MongoDB ?
    5. QCM

      Quel composant permet de répartir les données sur plusieurs serveurs MongoDB ?