Comprendre les paradigmes et choisir la bonne approche
Module NoSQL - École d'Ingénieurs
Relationnel vs Document
Embedding vs Referencing
Cas pratiques et migration
Performance vs Cohérence
Anti-patterns à éviter
E-commerce, Social, IoT
Comprendre les différences philosophiques
💡 MongoDB favorise la localité des données pour des performances optimales
-- 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
);
{
"_id": ObjectId(),
"title": "Mon article",
"content": "Contenu...",
"author": {
"name": "Ahmed",
"email": "ahmed@email.com"
},
"comments": [
{
"user": "Fatima",
"comment": "Excellent!",
"date": ISODate()
}
]
}
| 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 |
Embedding vs Referencing
{
"_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"
}
}
// 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"
}
{
"_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
↓ OUI : EMBED
↓ OUI : EMBED
↓ OUI : EMBED
↓ OUI : REFERENCE
De la théorie à la pratique
productscategoriesproduct_categoriesinventorypricesreviews6 tables, 5 jointures pour afficher un produit
{
"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
Identifier les requêtes fréquentes
Données accédées ensemble
Accepter la duplication contrôlée
80% read, 20% write
Limite 16MB par document
Mesurer les performances
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 }
]
}
Hiérarchies avec chemins
{
"name": "Électronique",
"path": "/shop/electronics",
"ancestors": [
{ "_id": "shop", "name": "Shop" }
]
}
Documents de types variés
{
"type": "product",
"sku": "CAF-001",
// Champs spécifiques au type
"size": ["S", "M", "L"]
}
Compromis et optimisations
| 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
Recréer un schéma SQL dans MongoDB
// MAUVAIS
orders → customers (ref)
orders → products (ref)
products → categories (ref)
products → suppliers (ref)
Tout mettre dans un seul document
// MAUVAIS
{
"user": "...",
"allOrders": [/* 10000 commandes */],
"allActivities": [/* 50000 logs */]
}
Arrays qui grandissent sans limite
// MAUVAIS
{
"post": "...",
"likes": [/* peut avoir 1M+ */]
}
Applications concrètes
{
"_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()
}
{
"_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
Conseils d'architecture
Exemples : Banque, ERP, Comptabilité
Exemples : E-commerce, CMS, IoT, Gaming
C'est un paradigme différent qui nécessite de repenser la modélisation
80% lectures ? Embed. Mises à jour fréquentes ? Reference.
La modélisation parfaite n'existe pas, testez et ajustez
Prochaine étape : Exercices pratiques de modélisation 🚀