MongoDB : requêtes et agrégation
Requêtes sur les collections clients et commandes. Tout se passe en JavaScript dans mongosh, dans la base boutique (use boutique).
db.clients.insertOne({ nom: 'Alice Martin', email: 'alice@exemple.com', ville: 'Lyon', tags: ['vip'],});
db.clients.insertMany([ { nom: 'Bruno Durand', email: 'bruno@exemple.com', ville: 'Paris', tags: ['web'], }, { nom: 'Chloé Petit', email: 'chloe@exemple.com', ville: 'Lyon', tags: ['web', 'mobile'], }, { nom: 'David Moreau', email: 'david@exemple.com', tags: [] },]);
const alice = db.clients.findOne({ email: 'alice@exemple.com' });db.commandes.insertMany([ { client_id: alice._id, montant: 49.9, statut: 'payee', passee_le: new Date(), }, { client_id: alice._id, montant: 120, statut: 'nouvelle', passee_le: new Date(), }, { client_id: db.clients.findOne({ nom: 'Bruno Durand' })._id, montant: 15.5, statut: 'payee', passee_le: new Date(), },]);Le résultat contient les _id générés (insertedId, insertedIds).
Lire des documents
Section intitulée « Lire des documents »db.clients.find();db.clients.find({ ville: 'Lyon' });db.clients.find({ ville: 'Lyon' }, { nom: 1, email: 1, _id: 0 }); // projection : champs affichés (1) ou masqués (0)db.clients.findOne({ email: 'bruno@exemple.com' });db.clients.find({ nom: /^a/i }); // expression régulièredb.clients.find({ ville: { $exists: false } }); // champ absentdb.clients.find().sort({ nom: -1 }).limit(2); // tri décroissant, 2 résultatsdb.clients.find().sort({ nom: 1 }).skip(2).limit(2); // paginationdb.clients.countDocuments({ ville: 'Lyon' });db.clients.distinct('ville');Opérateurs de comparaison et logiques
Section intitulée « Opérateurs de comparaison et logiques »| Opérateur | Sens | Exemple |
|---|---|---|
$eq, $ne |
égal, différent | { statut: { $ne: "annulee" } } |
$gt, $gte, $lt, $lte |
comparaisons | { montant: { $gte: 20, $lt: 200 } } |
$in, $nin |
dans, hors d’une liste | { ville: { $in: ["Lyon", "Paris"] } } |
$and, $or, $nor, $not |
logique | { $or: [{ ville: "Lyon" }, { tags: "vip" }] } |
$exists |
champ présent | { ville: { $exists: true } } |
$regex |
expression régulière | { nom: { $regex: "^A" } } |
$size |
taille d’un tableau | { tags: { $size: 2 } } |
$elemMatch |
élément de tableau satisfaisant plusieurs conditions | { lignes: { $elemMatch: { produit: "Clavier", quantite: { $gte: 1 } } } } |
db.commandes.find({ montant: { $gte: 20, $lt: 200 }, statut: 'payee' });db.clients.find({ $or: [{ ville: 'Lyon' }, { tags: 'vip' }] });db.clients.find({ tags: 'web' }); // un tableau contenant « web »db.commandes.find({ passee_le: { $gte: new Date(Date.now() - 7 * 24 * 3600 * 1000) },}); // 7 derniers joursModifier
Section intitulée « Modifier »db.clients.updateOne( { email: 'david@exemple.com' }, { $set: { ville: 'Marseille' } },);db.commandes.updateMany({ statut: 'nouvelle' }, { $set: { statut: 'payee' } });db.clients.updateOne( { email: 'alice@exemple.com' }, { $push: { tags: 'fidele' } },);db.clients.updateOne( { email: 'alice@exemple.com' }, { $addToSet: { tags: 'vip' } },); // sans doublondb.clients.updateOne( { email: 'alice@exemple.com' }, { $pull: { tags: 'fidele' } },);db.commandes.updateOne({}, { $inc: { montant: 5 } }); // incrémentedb.clients.updateOne({ email: 'david@exemple.com' }, { $unset: { ville: '' } }); // supprime un champdb.clients.findOneAndUpdate( { email: 'bruno@exemple.com' }, { $set: { ville: 'Nice' } }, { returnDocument: 'after' },);| Opérateur | Effet |
|---|---|
$set, $unset |
Définit ou supprime un champ |
$inc |
Incrémente un nombre |
$push, $addToSet, $pull |
Ajoute, ajoute sans doublon, retire un élément de tableau |
$rename |
Renomme un champ |
$currentDate |
Définit la date courante |
Insérer ou mettre à jour (upsert)
Section intitulée « Insérer ou mettre à jour (upsert) »db.clients.updateOne( { email: 'emma@exemple.com' }, { $set: { nom: 'Emma Roux' }, $setOnInsert: { cree_le: new Date() } }, { upsert: true },);Si aucun document ne correspond, il est créé (et $setOnInsert ne s’applique qu’à la création).
Supprimer
Section intitulée « Supprimer »db.commandes.deleteOne({ statut: 'annulee' });db.commandes.deleteMany({ statut: 'annulee' });db.clients.findOneAndDelete({ email: 'emma@exemple.com' });Agrégation
Section intitulée « Agrégation »Une agrégation enchaîne des étapes qui transforment les documents (équivalent de GROUP BY et des jointures).
// Total et nombre de commandes par statutdb.commandes.aggregate([ { $group: { _id: '$statut', nb: { $sum: 1 }, total: { $sum: '$montant' }, moyenne: { $avg: '$montant' }, }, }, { $sort: { total: -1 } },]);
// Clients ayant dépensé plus de 100db.commandes.aggregate([ { $match: { statut: { $ne: 'annulee' } } }, { $group: { _id: '$client_id', total: { $sum: '$montant' } } }, { $match: { total: { $gt: 100 } } },]);
// Jointure avec $lookup : ajouter les informations du client à chaque commandedb.commandes.aggregate([ { $lookup: { from: 'clients', localField: 'client_id', foreignField: '_id', as: 'client', }, }, { $unwind: '$client' }, { $project: { _id: 0, montant: 1, statut: 1, client: '$client.nom' } },]);
// Nombre de clients par villedb.clients.aggregate([ { $group: { _id: '$ville', nb: { $sum: 1 } } }, { $sort: { nb: -1 } },]);| Étape | Rôle |
|---|---|
$match |
Filtre (comme find) : à placer le plus tôt possible pour utiliser un index |
$group |
Regroupe et calcule ($sum, $avg, $min, $max, $count, $push) |
$project |
Choisit ou calcule des champs |
$sort, $limit, $skip |
Tri et pagination |
$lookup |
Jointure avec une autre collection |
$unwind |
Éclate un tableau en un document par élément |
$count |
Compte les documents en sortie |
Transactions
Section intitulée « Transactions »Les opérations sur un seul document sont atomiques. Les transactions multi-documents (session.startTransaction()) nécessitent un jeu de réplicas (replica set) : elles ne sont pas disponibles sur une instance simple (standalone).
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Manuel : CRUD Operations et Aggregation
- Suite : Utilisateurs et droits