1 / 25
🗄️
🍃

Modélisation des Données

MongoDB vs SQL

Comprendre les paradigmes et choisir la bonne approche

Module NoSQL - École d'Ingénieurs

Agenda

🎯 Paradigmes fondamentaux

Relationnel vs Document

🔄 Patterns de modélisation

Embedding vs Referencing

🏗️ Conception de schémas

Cas pratiques et migration

⚖️ Trade-offs

Performance vs Cohérence

🛠️ Bonnes pratiques

Anti-patterns à éviter

💼 Cas d'usage réels

E-commerce, Social, IoT

🎯 Paradigmes Fondamentaux

Comprendre les différences philosophiques

Relationnel vs Document

🗄️ SQL (Relationnel)

  • Structure : Tables, lignes, colonnes
  • Schéma : Fixe et défini à l'avance
  • Relations : Clés étrangères
  • Normalisation : 3NF, BCNF
  • Intégrité : Contraintes ACID
  • Requêtes : Jointures complexes

🍃 MongoDB (Document)

  • Structure : Collections, documents
  • Schéma : Flexible et dynamique
  • Relations : Embedding ou références
  • Dénormalisation : Données dupliquées
  • Performance : Lecture optimisée
  • Requêtes : Documents autonomes

💡 MongoDB favorise la localité des données pour des performances optimales

Exemple : Modéliser un Blog

🗄️ Modèle SQL

-- Table users
CREATE TABLE users (
  id INT PRIMARY KEY,
  name VARCHAR(100),
  email VARCHAR(100)
);

-- Table posts
CREATE TABLE posts (
  id INT PRIMARY KEY,
  user_id INT FOREIGN KEY,
  title VARCHAR(200),
  content TEXT
);

-- Table comments
CREATE TABLE comments (
  id INT PRIMARY KEY,
  post_id INT FOREIGN KEY,
  user_id INT FOREIGN KEY,
  comment TEXT
);

🍃 Modèle MongoDB

{
  "_id": ObjectId(),
  "title": "Mon article",
  "content": "Contenu...",
  "author": {
    "name": "Ahmed",
    "email": "ahmed@email.com"
  },
  "comments": [
    {
      "user": "Fatima",
      "comment": "Excellent!",
      "date": ISODate()
    }
  ]
}

Critères de choix

Critère SQL MongoDB
Relations complexes Excellent Limité
Schéma évolutif Rigide Flexible
Transactions ACID Natif Supporté (v4+)
Scalabilité horizontale Complexe Natif
Performance lecture Jointures Document unique
Données hiérarchiques Complexe Naturel

🔄 Patterns de Modélisation

Embedding vs Referencing

Pattern : Embedding (Imbrication)

📦 Intégrer les données liées dans le document

{
  "_id": ObjectId(),
  "orderNumber": "CMD-2024-001",
  "customer": {  // Données client intégrées
    "name": "Fatima Benali",
    "email": "fatima@email.com"
  },
  "items": [  // Produits intégrés
    {
      "sku": "CAF-001",
      "name": "Caftan",
      "price": 2500,
      "quantity": 1
    }
  ],
  "shipping": {  // Adresse intégrée
    "address": "45 Bd Mohammed V, Rabat",
    "method": "Amana"
  }
}

✅ Avantages

  • Performance lecture optimale
  • Données atomiques
  • Pas de jointures

❌ Inconvénients

  • Duplication de données
  • Document size limit (16MB)
  • Mises à jour complexes

Pattern : Referencing (Référence)

🔗 Référencer les données par ID

// Document Order
{
  "_id": ObjectId("507f1f77..."),
  "orderNumber": "CMD-2024-001",
  "customerId": ObjectId("507f191e..."),  // Référence
  "itemIds": [  // Références aux produits
    ObjectId("507f1f77..."),
    ObjectId("507f1f78...")
  ]
}

// Document Customer (séparé)
{
  "_id": ObjectId("507f191e..."),
  "name": "Fatima Benali",
  "email": "fatima@email.com"
}

✅ Avantages

  • Pas de duplication
  • Documents plus petits
  • Mises à jour simples

❌ Inconvénients

  • Requêtes multiples
  • Pas de jointures natives
  • Cohérence manuelle

Pattern : Hybride

🎯 Combiner Embedding et Referencing

{
  "_id": ObjectId(),
  "title": "Introduction à MongoDB",
  "author": {  // Données essentielles intégrées
    "id": ObjectId("507f191e..."),
    "name": "Dr. Ahmed",
    "avatar": "/avatars/ahmed.jpg"
  },
  "content": "...",
  "comments": [  // 10 derniers commentaires intégrés
    {
      "user": "Fatima",
      "text": "Excellent article!",
      "date": ISODate()
    }
  ],
  "commentCount": 47,  // Total pour pagination
  "tags": ["mongodb", "nosql"]
}

💡 Stratégie : Intégrer les données fréquemment accédées, référencer le reste

Arbre de décision : Embed ou Reference ?

Les données ont-elles une relation 1:1 ?

↓ OUI : EMBED

↓ NON
La relation est-elle 1:N avec N petit (< 100) ?

↓ OUI : EMBED

↓ NON
Les données sont-elles toujours accédées ensemble ?

↓ OUI : EMBED

↓ NON
Les données changent-elles indépendamment ?

↓ OUI : REFERENCE

🏗️ Conception de Schémas

De la théorie à la pratique

Cas pratique : E-commerce

🗄️ Approche SQL

  • Table products
  • Table categories
  • Table product_categories
  • Table inventory
  • Table prices
  • Table reviews

6 tables, 5 jointures pour afficher un produit

🍃 Approche MongoDB

{
  "sku": "CAF-001",
  "name": "Caftan Premium",
  "categories": ["Vêtements", "Traditionnel"],
  "price": { "amount": 2500, "currency": "MAD" },
  "inventory": { "quantity": 15, "warehouse": "Casa" },
  "reviews": { "average": 4.8, "count": 127 }
}

1 document, toutes les infos

Migration : SQL → MongoDB

1️⃣ Analyser les jointures

Identifier les requêtes fréquentes

2️⃣ Regrouper par entité

Données accédées ensemble

3️⃣ Dénormaliser

Accepter la duplication contrôlée

4️⃣ Optimiser pour les lectures

80% read, 20% write

5️⃣ Prévoir la croissance

Limite 16MB par document

6️⃣ Tester et itérer

Mesurer les performances

Patterns de modélisation avancés

📊 Bucket Pattern

Regrouper des données temporelles

{
  "sensor": "temp-001",
  "hour": ISODate("2024-03-20T14:00:00"),
  "readings": [
    { "minute": 0, "temp": 22.5 },
    { "minute": 15, "temp": 22.7 }
  ]
}

🌳 Tree Pattern

Hiérarchies avec chemins

{
  "name": "Électronique",
  "path": "/shop/electronics",
  "ancestors": [
    { "_id": "shop", "name": "Shop" }
  ]
}

🔄 Polymorphic Pattern

Documents de types variés

{
  "type": "product",
  "sku": "CAF-001",
  // Champs spécifiques au type
  "size": ["S", "M", "L"]
}

⚖️ Trade-offs

Compromis et optimisations

Performance vs Cohérence

Aspect Embedding Referencing
Performance lecture Excellent Multiple requêtes
Performance écriture Updates multiples Update unique
Cohérence Duplication Source unique
Taille document Peut grandir Prévisible
Complexité app Simple Gestion refs

💡 Règle d'or : Optimisez pour vos cas d'usage principaux

Anti-patterns à éviter

❌ Normalisation excessive

Recréer un schéma SQL dans MongoDB

// MAUVAIS
orders → customers (ref)
orders → products (ref)
products → categories (ref)
products → suppliers (ref)

❌ Documents géants

Tout mettre dans un seul document

// MAUVAIS
{
  "user": "...",
  "allOrders": [/* 10000 commandes */],
  "allActivities": [/* 50000 logs */]
}

❌ Arrays illimités

Arrays qui grandissent sans limite

// MAUVAIS
{
  "post": "...",
  "likes": [/* peut avoir 1M+ */]
}

💼 Cas d'Usage Réels

Applications concrètes

Cas : Réseau Social

👥 Modélisation d'un post

{
  "_id": ObjectId(),
  "author": {  // Embed : toujours affiché
    "id": ObjectId(),
    "username": "@fatima",
    "avatar": "/avatars/fatima.jpg"
  },
  "content": "Magnifique coucher de soleil à Essaouira! 🌅",
  "images": ["/posts/sunset1.jpg"],
  "stats": {  // Compteurs dénormalisés
    "likes": 342,
    "comments": 28,
    "shares": 15
  },
  "recentLikes": [  // Derniers 3 pour preview
    { "username": "@ahmed", "avatar": "/avatars/ahmed.jpg" }
  ],
  "topComments": [  // 2 meilleurs commentaires
    {
      "author": "@sara",
      "text": "Sublime! 😍",
      "likes": 24
    }
  ],
  "createdAt": ISODate()
}

Cas : IoT / Time Series

📊 Pattern Bucket pour capteurs

{
  "_id": ObjectId(),
  "metadata": {
    "sensorId": "temp-factory-01",
    "type": "temperature",
    "location": "Usine Casablanca",
    "unit": "celsius"
  },
  "startTime": ISODate("2024-03-20T14:00:00Z"),
  "endTime": ISODate("2024-03-20T15:00:00Z"),
  "measurements": [
    { "t": 0, "v": 22.5 },    // t=minutes, v=value
    { "t": 5, "v": 22.7 },
    { "t": 10, "v": 23.1 }
  ],
  "stats": {  // Pré-calculés
    "min": 22.5,
    "max": 23.8,
    "avg": 23.1,
    "count": 12
  }
}

💡 1 document = 1 heure de données = Requêtes optimisées

🛠️ Bonnes Pratiques

Conseils d'architecture

10 Règles d'or MongoDB

1. Données ensemble = Document unique

2. Éviter les jointures applicatives

3. Préférer la duplication contrôlée

4. Arrays bornés uniquement

5. Index sur tous les champs de requête

6. Documents < 5MB idéalement

7. Schéma évolutif mais cohérent

8. Pré-calculer les agrégations

9. Utiliser les transactions si nécessaire

10. Monitorer et optimiser

Résumé : Choisir la bonne approche

🗄️ Choisir SQL quand...

  • Relations complexes many-to-many
  • Intégrité référentielle critique
  • Transactions ACID complexes
  • Reporting avec jointures multiples
  • Schéma stable et bien défini
  • Équipe familière avec SQL

Exemples : Banque, ERP, Comptabilité

🍃 Choisir MongoDB quand...

  • Données hiérarchiques/imbriquées
  • Schéma évolutif fréquemment
  • Performance lecture critique
  • Scalabilité horizontale requise
  • Données semi-structurées
  • Développement agile/itératif

Exemples : E-commerce, CMS, IoT, Gaming

Points clés à retenir

🎯 MongoDB != SQL sans schéma

C'est un paradigme différent qui nécessite de repenser la modélisation

📊 Optimiser pour les cas d'usage

80% lectures ? Embed. Mises à jour fréquentes ? Reference.

🔄 Itérer et mesurer

La modélisation parfaite n'existe pas, testez et ajustez

Prochaine étape : Exercices pratiques de modélisation 🚀