Plan
Plan
Introduction
1. Terminologie
SQL VS no-SQL
Relationnel VS non-relationnel
2. Le modèle relationnel
Relationnel VS non-relationnel
3. Différents paradigmes alternatifs
Orienté document
Orienté clé-valeur
Orienté graph
Orienté colonnes
3.1 La distribution
4. Le théorème CAP
1 / 12
Plan
MongoDB
1. Relationnel VS Orienté document
1.1 Table VS Collection
La table La collection
est composée des colonnes et des est composée de documents
lignes
est structurée par un schéma est éventuellement structurée par un
validateur
DOIT être normalisée PEUT être normalisée
est mise en relation via des clés est mise en relation par imbrication ou par
étrangères référence
forme avec les autres tables un peut être shardée ou former un ensemble qui
ensemble qui peut être repliqué peut être répliqué
2 / 12
Plan
La table La collection
supporte les jointures ne supporte pas les jointures. Plusieurs
requêtes peuvent être nécessaires
1.2 Le paradigme orienté document
MongoDB permet plein de choses, mais est plus pertinent dans certaines situations.
Le paradigme orienté document encourage :
Des collections indépendantes qui peuvent être shardées
Des documents imbriquées qui peuvent être récupérés en une seule requête
Un modèle dénormalisé
Des données non-structurées
1.3 Cas d'utilisations
1.3.1 Quand préférer MongoDB ?
Les bases de données NoSQL permettent plus de flexibilité.
Pour stocker des journaux
Pour conserver des données dans leur état d'origine (eg, adresse dans facture,
questions dans un contrôle, etc.)
Dans le cadre d'un développement itératif rapide (pas besoin de modifier le schéma)
Dans le cadre d'un développement avec NodeJS
Lorsque la charge en lecture est bien supérieur à la charge en écriture
Lorsqu'il faut manipuler des gros volumes de données simultanées
Lorsque l'on souhaite travailler sur un système hautement distribué
1.3.2 Quand préférer MariaDB ?
Les bases de données relationnelles permettent plus de consistance (et donc de stabilité).
Lorsque les données sont très fortement interconnectées
Lorsque les données doivent avoir un haut niveau de normalisation
Lorsque l'on souhaite réaliser des jointures complexes
Lorsque la charge en écriture est plus importante que la charge en lecture
Lorsque l'on souhaite travailler sur un système hautement centralisé
2. Opérations CRUD basiques
Pour commencer à utiliser une base de données, il suffit d'appeler :
3 / 12
Plan
use library
Inutile de créer explicitement la base de données ou les collections qui la compose comme
on le ferait avec une BDD relationnelle.
2.1 Create
// insertOne
[Link]({
"author": "Chinua Achebe",
"title": "Things Fall Apart",
"year": 1958
})
// insertMany
[Link]([
{
"author": "J.R.R. Tolkien",
"title": "The Hobbit",
"year": 1937
},
{
"author": "J.R.R. Tolkien",
"title": "The Fellowship of the Ring",
"year": 1954
},
{
"author": "J.R.R. Tolkien",
"title": "The Return of the King",
"year": 1954
}
])
2.2 Read
// find
[Link]()
[Link]({ "author": "J.R.R. Tolkien" })
// findOne
[Link]({ "author": "Chinua Achebe" })
2.3 Update
// updateOne
[Link](
4 / 12
Plan
{ "title": "The Return of the King" },
{ "$set": { "year": 1955 } }
)
// updateMany
[Link](
{},
{ "$set": { "available": true } }
)
[Link](
{ "year": { "$gt": 1950 } },
{ "$set": { "available": false } }
)
2.4 Delete
// deleteOne
[Link]({ "author": "Chinua Achebe" })
// deleteMany
[Link]({ "available": false })
3. Les opérateurs de requête
3.1. Opérateurs de comparaison
Opérateur Description Exemple
$eq Égal à { age: { $eq: 25 } }
$ne Différent de { age: { $ne: 25 } }
$gt Supérieur à { age: { $gt: 25 } }
$gte Supérieur ou égal à { age: { $gte: 25 } }
$lt Inférieur à { age: { $lt: 25 } }
$lte Inférieur ou égal à { age: { $lte: 25 } }
$in Dans une liste de valeurs { age: { $in: [20, 25, 30] } }
$nin Pas dans une liste de valeurs { age: { $nin: [20, 25, 30] } }
3.2 Opérateurs logiques
Opérateur Exemple
$and { $and: [ { age: { $gt: 20 } }, { age: { $lt: 30 } ] } }
5 / 12
Plan
Opérateur Exemple
$or { $or: [ { age: { $lt: 20 } }, { age: { $gt: 30 } } ] }
$not { age: { $not: { $gt: 30 } } }
$nor { $nor: [ { age: { $gt: 30 } }, { age: { $lt: 20 } } ] }
3.3 Opérateurs de type
Opérateur Description Exemple
$type Filtre par type { age: { $type: "number" } }
$exists Vérifie la présence d’un champ { age: { $exists: true } }
3.4 Opérateurs de tableau
Opérateur Description Exemple
$elemMatch Recherche un élément { tags: { $elemMatch: { name:
répondant à plusieurs "mongodb", score: { $gt: 90 } } }
conditions }
$size Vérifie la taille d’un tableau { tags: { $size: 3 } }
$all Contient tous les éléments { tags: { $all: ["mongodb",
spécifiés "database"] } }
3.5 Opérateurs d'évaluation
Opérateur Exemple
$expr { $expr: { $gt: [ "$spent" , "$budget" ] } }
$jsonSchema CF:
[Link]
$mod { qty: { $mod: [ 4, 0 ] } }
$regex { name: { $regex: 'acme.*corp', $options: "si" } }
$where { $where: function() { return (hex_md5([Link]) ==
"9b53e667f30cd329dca1ec9e6a83e994") } }
4. Les opérateurs de mise à jour
$currentDate Sets the value of a field to current date, either as a Date or a Timestamp.
6 / 12
Plan
$inc Increments the value of the field by the specified amount.
$min Only updates the field if the specified value is less than the existing field
value.
$max Only updates the field if the specified value is greater than the existing
field value.
$mul Multiplies the value of the field by the specified amount.
$rename Renames a field.
$set Sets the value of a field in a document.
$setOnInsert Sets the value of a field if an update results in an insert of a document.
Has no effect on update operations that modify existing documents.
$unset Removes the specified field from a document.
$ Acts as a placeholder to update the first element that matches the
query condition.
$[] Acts as a placeholder to update all elements in an array for the
documents that match the query condition.
$[<identifier>] Acts as a placeholder to update all elements that match the
arrayFilters condition for the documents that match the query
condition.
$addToSet Adds elements to an array only if they do not already exist in the set.
$pop Removes the first or last item of an array.
$pull Removes all array elements that match a specified query.
$push Adds an item to an array.
$pullAll Removes all matching values from an array.
5. Types
6. Modélisation de BDD avec mongoDB
6.1 Embedded VS reference
// embedded
[Link]({
title: "Les Misérables",
genre: "Fiction",
publicationYear: 1862,
author: {
name: "Victor Hugo",
birthYear: 1802,
nationality: "French",
7 / 12
Plan
awards: ["Légion d'honneur"]
},
pages: 1232
})
// reference
const authorId = [Link]({
name: "Victor Hugo",
birthYear: 1802,
nationality: "French",
awards: ["Légion d'honneur"]
}).insertedId;
[Link]({
title: "Les Misérables",
genre: "Fiction",
publicationYear: 1862,
author: authorId,
pages: 1232
});
6.2 Query embedded
[Link]({ '[Link]': 'Victor Hugo' })
6.3 Query reference
[Link]([
{
$lookup: {
from: 'authors',
localField: 'author',
foreignField: '_id',
as: 'author'
}
},
{
$match: { '[Link]': 'Victor Hugo' }
}
])
6.3.1 Exemple complèxe
8 / 12
Plan
[Link]([
{ "_id": 1, "name": "Alice" },
{ "_id": 2, "name": "Bob" }
]);
[Link]([
{ "_id": 1001, "name": "Laptop", "price": 1000 },
{ "_id": 1002, "name": "Phone", "price": 500 }
]);
[Link]([
{ "_id": 101, "userId": 1, "productId": 1001, "quantity": 2 },
{ "_id": 102, "userId": 1, "productId": 1002, "quantity": 1 },
{ "_id": 103, "userId": 2, "productId": 1002, "quantity": 1 },
{ "_id": 104, "userId": 2, "productId": 1002, "quantity": 1 }
]);
[Link]([
{
$lookup: {
from: "orders", // Collection `orders` à joindre
localField: "_id", // Champ local dans `users`
foreignField: "userId", // Champ correspondant dans `orders`
as: "userOrders" // Nom du champ contenant les données jointes
}
},
{ $unwind: "$userOrders" },
{
$lookup: {
from: "products", // Collection `products` à joindre
localField: "[Link]", // Champ local dans `orders`
foreignField: "_id", // Champ correspondant dans `products`
as: "productDetails" // Nom du champ contenant les données
jointes
}
},
{ $unwind: "$productDetails" },
{
$project: {
_id: 1,
name: 1,
"orderId": "$userOrders._id",
"productName": "$[Link]",
"productPrice": "$[Link]",
"quantity": "$[Link]"
}
}
]);
[Link]([
{
$lookup: {
9 / 12
Plan
from: "orders", // Collection `orders` à
joindre
localField: "_id", // Champ local dans `users`
foreignField: "userId", // Champ correspondant dans
`orders`
as: "userOrders" // Nom du champ contenant les
données jointes
}
},
{ $unwind: "$userOrders" },
{
$lookup: {
from: "products", // Collection `products` à joindre
localField: "[Link]", // Champ local dans `orders`
foreignField: "_id", // Champ correspondant dans `products`
as: "productDetails" // Nom du champ contenant les données
jointes
}
},
]);
7. Les aggregats
[Link]([
{ nom: "Laptop", categorie: "Electronique", prix: 1200, stock: 50, note:
4.5, ventes: 200 },
{ nom: "Téléphone", categorie: "Electronique", prix: 800, stock: 100,
note: 4.7, ventes: 500 },
{ nom: "Table", categorie: "Meuble", prix: 150, stock: 20, note: 4.1,
ventes: 30 },
{ nom: "Chaise", categorie: "Meuble", prix: 75, stock: 150, note: 3.8,
ventes: 120 },
{ nom: "Casque Audio", categorie: "Electronique", prix: 200, stock: 80,
note: 4.6, ventes: 300 },
{ nom: "Lampe", categorie: "Décoration", prix: 40, stock: 200, note: 4.0,
ventes: 80 },
{ nom: "Canapé", categorie: "Meuble", prix: 600, stock: 15, note: 4.4,
ventes: 20 },
{ nom: "Montre", categorie: "Accessoire", prix: 300, stock: 50, note: 4.8,
ventes: 150 },
{ nom: "Sac à dos", categorie: "Accessoire", prix: 90, stock: 70, note:
4.2, ventes: 100 },
{ nom: "Tapis", categorie: "Décoration", prix: 120, stock: 30, note: 4.3,
ventes: 60 }
]);
10 / 12
Plan
// 1. Regrouper par catégorie et afficher le prix moyen
[Link]([
{ $group: { _id: "$categorie", prixMoyen: { $avg: "$prix" } } }
]);
// 2. Trier les produits par nombre de ventes décroissant
[Link]([
{ $sort: { ventes: -1 } }
]);
// 3. Afficher les catégories ayant un total de ventes supérieur à 100
[Link]([
{ $group: { _id: "$categorie", totalVentes: { $sum: "$ventes" } } },
{ $match: { totalVentes: { $gt: 100 } } }
]);
// 4. Trouver le produit le plus cher dans chaque catégorie
[Link]([
{ $sort: { prix: -1 } },
{ $group: { _id: "$categorie", produitLePlusCher: { $first: "$nom" } } }
]);
// 5. Calculer le stock total disponible pour chaque catégorie
[Link]([
{ $group: { _id: "$categorie", stockTotal: { $sum: "$stock" } } }
]);
// 6. Calculer le revenu potentiel (prix * ventes) pour chaque produit
[Link]([
{ $project: { nom: 1, revenuPotentiel: { $multiply: ["$prix", "$ventes"] }
} }
]);
// 7. Afficher les produits avec une note supérieure à 4.5
[Link]([
{ $match: { note: { $gt: 4.5 } } }
]);
// 8. Ajouter une catégorie de prix ("Élevé", "Moyen", "Bas") en fonction du
prix
[Link]([
{ $addFields: { categoriePrix: {
$cond: { if: { $gt: ["$prix", 500] }, then: "Élevé", else: {
$cond: { if: { $gt: ["$prix", 100] }, then: "Moyen", else: "Bas" }
}}
}}
}
]);
11 / 12
Plan
// 9. Calculer la note moyenne des produits dans chaque catégorie
[Link]([
{ $group: { _id: "$categorie", noteMoyenne: { $avg: "$note" } } }
]);
// 10. Regrouper les produits par catégorie et inclure une liste de leurs
noms
[Link]([
{ $group: { _id: "$categorie", produits: { $push: "$nom" } } }
]);
12 / 12