Aggregate:project,$match,$group,$sort,$limit,$skip,$count

c'est une fonction qui permet d'appliquer une listes de filters(pipeline) sur des documents d'une collection,
Exemple:
  • $group: grouper les résultats par un ou plusieurs attributs
    Afficher le nombre de produits par marque
    Afficher la quantité totale d'un produit
  • $match
  • $sort
  • $limit
  • $skip
  • ...

Aggregate:syntaxe

db.Nomcollection.aggregate([ { $match:Les conditions comme dans find},
{$group:...},
{$sort:...}
{$limit:...}
{$project:...}
]);
  • $match: Permet d'appliquer une condtion ou plusieurs
  • $sort: Permet de trier les resultats
  • $limit: Permet d'afficher un nombre de résultats défini
  • $project: Permet d'afficher quelque attributs

$match

Afficher les produits de la marque marqueA
db.produits.aggregate([ {$match:{"marque":"marqueA"}}])
Afficher les produits de la marque marqueA et le fournisseur nom=fournisseur1
db.produits.aggregate([
{$match:{ $and:[{"marque":"marqueA"},
{"fournisseur.nom":"fournisseur1"}]}}])
Afficher les produits des catégories suivantes: categorie1 ,categorie2 et categorie3
db.produits.aggregate([ {$match:{ "categories.nom":{$in:["categorie1","categorie2","categorie3"]}}}])

$project

$project: permet de spécifier les attributs à afficher
Exemples:
Afficher le nom et le prix de tous les produits qui ont prix>100
db.produits.aggregate([
{$match:{"prix":{$gt:100}}},
{$project:{"nom":1,"prix":1,"_id":0}}
])

$sort

$sort: permet de trier les résultats selon un ou plusieurs attributs
Exemples:
Afficher le nom , prix et marque des produits du fournisseur nom=fournisseur1 trier par marque
db.produits.aggregate([
{$match:{"fournisseur.nom":"fournisseur1"}},
{$sort:{"marque":1}},
{$project:{"nom":1,"prix":1,"marque":1,"_id":0}}
])

$limit

$limit: permet de spécifier le nombre de résultats à afficher
Exemples:
Afficher le nom ,le prix et la marque des deux premiers produits de la catégorie categorie1 triés par leur prix en ordre décroissant
db.produits.aggregate([
{$match:{"categories.nom":"categorie1"}},
{$sort:{"prix":-1}},
{$limit:2},
{$project:{"nom":1,"prix":1,"marque":1,"_id":0}}
])
retourne:
{
  nom: 'xzz',
  prix: 1000,
  marque: 'marqueA'
},
{
  nom: 'abcd',
  prix: 100,
  marque: 'marqueB'
}

$limit and $skip

$skip: permet d'ignorer les premiers x résultats
Exemples:
Afficher le nom ,le prix et la marque des du troisième produit produits de la catégorie categorie1 triés par leur prix en ordre décroissant
db.produits.aggregate([
{$match:{"categories.nom":"categorie1"}},
{$sort:{"prix":-1}},
{$skip:2},
{$limit:1},
{$project:{"nom":1,"prix":1,"marque":1,"_id":0}}
])

$count

$skip: permet de compter le nombre de résultats retourné
Exemples:
Afficher le nombre de produits qui ont prix<10
db.produits.aggregate([
{$match:{"prix":{$lt:10}}},
{$count:"nombreProduit"}
])

$group,$sum

$group: permet de grouper les résultats selon un ou plusieurs attributs
Exemples:
Afficher la quantité totale pour chaque marque
db.produits.aggregate([
{$group:{_id:"$marque",quantiteTotale:{$sum:"$quantite"}}} ])
{_id:"marque":
_id: est un attribut de l'opérateur $group n'as pas de relation avec _id du document
"marque": est l'attribut utilisé pour grouper les resutlats
select sum(quantite),marque from produits group by marque
Afficher la quantité totale pour chaque marque puis les trier en ordre croissant selon cette quantité totale
db.produits.aggregate([
{$group:{_id:"$marque",quantiteTotale:{$sum:"$quantite"}}},
{$sort:{quantiteTotale:1}} ])
Afficher le nombre de produits par marque de la catégorie categorie1 puis les trier en ordre décroissant selon ce nombre
db.produits.aggregate([ {$match:{"categories.nom":"categorie1"}},
{$group:{_id:"$marque",nombre:{$sum:1}}},
{$sort:{nombre:-1} ])
Solution 2 avec $count
db.produits.aggregate([ {$match:{"categories.nom":"categorie1"}},
{$group:{_id:"$marque",nombre:{$count:{}}}},
{$sort:{nombre:-1} ])
retourne:
{
  _id: 'marqueB',
  nombre: 100
},

{
  _id: 'marqueB',
  nombre: 10
}

$group,$avg

$avg: permet de calculer la moyenne selon un attribut (group)
Afficher la moyenne des prix par marque
db.produits.aggregate([
{$group:{_id:"$marque",moyennePrix:{$avg:"$prix"}}}])
{
  _id: 'marqueB',
  moyennePrix: 55
},
{
  _id: 'marqueA',
  moyennePrix: 1000
}
Afficher les marques qui ont la moyenne de leur prix <10
db.produits.aggregate([
{$group:{_id:"$marque",moyennePrix:{$avg:"$prix"}}},
{$match:{moyennePrix:{$lt:10}}}])

$set

Permet d'ajouter un attribut dans le document
Ajouter pour chaque document le nombre totale de tous les produits
Ajouter pour chaque document l'attribut type="level1" si la moyenne des prix de la marque de ce produits >1000
Ajouter pour chaque produit dans l'objet founisseur l'attribut appeler=true si l'un de ces produits ont quantite=0
Diminuer le prix de tous les produits par 5 si la moyenne de prix de sa marque >1000
Ajouter dans le tableau sizes de chaque produit la valeur 100 si le prix=100

$unwind

Permet de de distribuer les valeurs d'un tableau sur chaque document
produits*categories=
répéter chaque produit pour chaque valeur dans le tableau categories

document:{ "_id" : 1, "item" : "ABC1", sizes: [ "S", "M", "L"] 

db.nomCollection.aggregate( [ { $unwind : "$sizes" } ] )
va produire:
{ "_id" : 1, "item" : "ABC1", "sizes" : "S" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "M" }
{ "_id" : 1, "item" : "ABC1", "sizes" : "L" }
Afficher la moyenne des prix par chaque categorie
db.produits.aggregate([
{$unwind:"categories"},
{$group:{_id:"$categories.nom",moyennePrix:{$avg:"$prix"}}}
])
(Erreur lorsque on groupe par les valeurs d'un tableau on doit utiliser ($unwind) voir cours $unwind,$set..
Solution:
db.produits.aggregate([
{$unwind:"$categories"},
{$group:{_id:"$categories.nom",moyennePrix:{$avg:"$prix"}}}
])
Résultats:
{
  _id: 'Low Cost',
  moyennePrix: 280
}
{
  _id: 'categorie1',
  moyennePrix: 550
}
{
  _id: 'categorie2',
  moyennePrix: 550
}
Afficher la listes des categories qui ont ou moins 3 produits
db.produits.aggregate([
{$unwind:"$categories"},
{$group:{_id:"$categories.nom",nombreProduits:{$sum:1}}	},
{$match:{"$nombreProduit":{$gte:3}}}])
Afficher pour chaque categories le prix le plus bas
db.produits.aggregate([
{$unwind:"$categories"},
{$group:{_id:"$categories.nom",minPrix:{$min:"$prix"}}	},
])
Résultats
{
  _id: 'Low Cost',
  minPrix: 10
}
{
  _id: 'categorie1',
  minPrix: 100
}
{
  _id: 'categorie2',
  minPrix: 100
}

Exercices

  • 1 Afficher les marques qui n'ont aucun produits dans le stock (quantité=0)
    db.produits.aggregate([
    {$group:{_id:"$marque",totaleStock:{$sum:"$quantite"}}},
    {$match:{totaleStock:{$eq:0}}}])
    
  • 2 Afficher les marques qui ont ou moins un produits avec le stock (quantité=0)
    db.produits.aggregate([
    {$match:{"quantite":{$eq:0}}},
    {$project:{"marque":1}}
    ])
  • 3.a Afficher le nombre de produits par fournisseur
    db.produits.aggregate([
    {$group:{_id:"$fournisseur",nombreProduits:{$sum:1}}}])
    Résultats:
    {
      _id: {
        _id: 2,
        nom: 'fournisseur5',
        tel: '6325455'
      },
      nombreProduits: 2
    },
    {
      _id: {
        _id: 2,
        nom: 'fournisseur1',
        tel: '6325455'
      },
      nombreProduits: 1
    }
  • 3.b Afficher les founrisseurs qui ont au moins 10 produits différents
    db.produits.aggregate([
    {$group:{_id:"$fournisseur",nombreProduits:{$sum:1}}},
    {$match:{nombreProduits:{$gt:10}}}
    ])
  • 4.a Afficher pour chaque marque le nombre des fournisseurs
  • 4.b Afficher les marques qui ont deux fournisseurs
  • 5 Afficher les frounisseur qui ont 3 marque
  • 6 Afficher le nombre de fournisseur par marque
  • 7.a Afficher la quantité totale par produit
    db.produits.aggregate([
    {$group:{_id:"$_id",totaleQuantite:{$sum:"$quantite"}}}
    ])
    
  • 7.b Afficher la quantité totale des produits
    db.produits.aggregate([
    {$group:{_id:null,totaleQuantite:{$sum:"$quantite"}}}
    ])
    
  • 8 Afficher la quantité totale par le nom du fournisseur et par marque
    db.produits.aggregate([
    {$group:{_id:
             {"fournisseur":"$fournisseur.nom","marque":"$marque" },
    		 quantiteTotale:{$sum:"$quantite"}
    	  }}
    ])
    
    Résultats:
    {
      _id: {
        fournisseur: 'fournisseur5',
        marque: 'marqueB'
      },
      quantiteTotale: 110
    },
    {
      _id: {
        fournisseur: 'fournisseur1',
        marque: 'marqueA'
      },
      quantiteTotale: 8
    }
    
  • 9 Afficher le totale des ventes (prix*quantité) pour chaque marque
    db.produits.aggregate([
    {$group:{_id:"$marque",venteTotale:{$sum:{$multiply:["$prix","$quantite"]}}}}])
    Résultats
    {
      _id: 'marqueA',
      venteTotale: 8000
    },
    {
      _id: 'marqueB',
      venteTotale: 10100
    }
  • 10 Afficher la moyenne des ventes (prix*quantité) pour chaque fournissuer par marque
    db.produits.aggregate([
    {$group:{_id:{"fournisseur":"$fournisseur.nom","marque":"$marque"},MoyenneVente:{$avg:{$multiply:["$prix","$quantite"]}}}}])
    Résultats
    {
      _id: {
        fournisseur: 'founisseur4',
        marque: 'marqueB'
      },
      MoyenneVente: 100
    },
    {
      _id: {
        fournisseur: 'fournisseur1',
        marque: 'marqueA'
      },
      MoyenneVente: 8000
    }
  • 11 Afficher les produits qui la moyenne des ventes (prix*quantité) par marque >1000
    db.produits.aggregate([
    {$group:{_id:"$marque",
    		MoyenneVente:{$avg:{$multiply:["$prix","$quantite"]}}}},
    {$match:{MoyenneVente:{$gt:1000}}}
    ])
  • 12 Afficher la quantité totale de tout les produits
    db.produits.aggregate([
    {$group:{_id:null,
           totaleQuantite:{$sum:"$quantite"}}}])
    Résultats
    {
      _id: null,
      totaleQuantite: 118
    }
  • 13 Afficher la quantité totale des ventes (quantite*prix) de tout les produits
    db.produits.aggregate([
    {$group:{_id:null,
    totaleVente:{$sum:{$multiply:["$quantite","$prix"]}}}}])
    Résultats
    {
      _id: null,
      totaleVente: 18100
    }
  • 14 Afficher le totale du tva par marque
    db.produits.aggregate([
    {$group:{_id:"$marque",
    totaleTVA:{$sum:{$multiply:["$quantite","$prix",0.2]}}}}])
    Résultats:
    {
      _id: 'marqueB',
      totaleTVA: 2020
    },
    {
      _id: 'marqueA',
      totaleTVA: 1600
    }
  • Exemples

    • Question 1 Comment puis-je obtenir le nom et le prix du produit "produit1" ?
      Réponse 1: Utilisez aggregate avec l'opérateur $match et $project pour obtenir le nom et le prix du produit "produit1" :
      db.produits.aggregate([
        { $match: { nom: "produit1" } },
        { $project: { _id: 0, nom: 1, prix: 1 } }
      ])
    • Question 2 Comment puis-je obtenir la liste des fournisseurs avec leur nom et numéro de téléphone ?
      Réponse 2: Utilisez aggregate avec l'opérateur $project pour obtenir la liste des fournisseurs avec leur nom et numéro de téléphone :
      db.produits.aggregate([
        { $project: { _id: 0, "fournisseurs.nom": 1, "fournisseurs.tel": 1 } }
      ])
    • Question 3 Comment puis-je regrouper les produits par marque et obtenir le nombre de produits par marque ?
      Réponse 3: Utilisez aggregate avec l'opérateur $group pour regrouper les produits par marque et compter le nombre de produits par marque :
      db.produits.aggregate([
        { $group: { _id: "$marque", nombre_de_produits: { $sum: 1 } } }
      ])
    • Question 4 Comment puis-je trier les produits par prix en ordre décroissant et obtenir les cinq produits les plus chers ?
      Réponse 4: Utilisez aggregate avec les opérateurs $sort, $limit pour trier les produits par prix en ordre décroissant et obtenir les cinq produits les plus chers :
      db.produits.aggregate([
        { $sort: { prix: -1 } },
        { $limit: 5 }
      ])
    • Question 5 Comment puis-je obtenir les produits dont la quantité est supérieure à 30 ?
      Réponse 5: Utilisez aggregate avec l'opérateur $match pour obtenir les produits dont la quantité est supérieure à 30 :
      db.produits.aggregate([
        { $match: { quantite: { $gt: 30 } } }
      ])
    • Question 6 Comment puis-je obtenir les produits dont le mois de promotion est "janvier" ou "mars" ?
      Réponse 6: Utilisez aggregate avec l'opérateur $match pour obtenir les produits dont le mois de promotion est "janvier" ou "mars" :
      db.produits.aggregate([
        { $match: { moisPromotions: { $in: ["janvier", "mars"] } } }
      ])
    • Question 7 Comment puis-je obtenir les catégories des produits avec leur nom et description ?
      Réponse 7: Utilisez aggregate avec l'opérateur $unwind et $project pour obtenir les catégories des produits avec leur nom et description :
      db.produits.aggregate([
        { $unwind: "$categories" },
        { $project: { _id: 0, "categories.nom": 1, "categories.description": 1 } }
      ])
    • Question 8 Comment puis-je obtenir le nombre total de produits ?
      Réponse 8: Utilisez aggregate avec l'opérateur $count pour obtenir le nombre total de produits :
      db.produits.aggregate([
        { $count: "total" }
      ])
    • Question 9 Comment puis-je obtenir les produits par page (par exemple, 10 produits par page) en sautant les 10 premiers produits ?
      Réponse 9: Utilisez aggregate avec les opérateurs $skip et $limit pour obtenir les produits par page en sautant les 10 premiers produits :
      db.produits.aggregate([
        { $skip: 10 },
        { $limit: 10 }
      ])
    • Question 10 Comment puis-je obtenir les produits triés par nom en ordre alphabétique ?
      Réponse 10: Utilisez aggregate avec l'opérateur $sort pour obtenir les produits triés par nom en ordre alphabétique :
      db.produits.aggregate([
        { $sort: { nom: 1 } }
      ])
    • Question 11 Comment puis-je obtenir le nom, la marque et le prix des produits triés par prix décroissant ?
      Réponse 11: Utilisez aggregate avec les opérateurs $project et $sort pour obtenir le nom, la marque et le prix des produits triés par prix décroissant :
      db.produits.aggregate([
        { $project: { _id: 0, nom: 1, marque: 1, prix: 1 } },
        { $sort: { prix: -1 } }
      ])
    • Question 12 Comment puis-je obtenir la liste des mois de promotion triés par ordre alphabétique et sans doublons ?
      Réponse 12: Utilisez aggregate avec les opérateurs $unwind, $sort et $group pour obtenir la liste des mois de promotion triés par ordre alphabétique et sans doublons :
      db.produits.aggregate([
        { $unwind: "$moisPromotions" },
        { $group: { _id: null, moisPromotions: { $addToSet: "$moisPromotions" } } },
        { $project: { _id: 0, moisPromotions: 1 } },
        { $unwind: "$moisPromotions" },
        { $sort: { "moisPromotions": 1 } }
      ])
    • Question 13 Comment puis-je obtenir le nom de la catégorie et le nombre de produits associés à chaque catégorie ?
      Réponse 13: Utilisez aggregate avec les opérateurs $unwind, $group et $project pour obtenir le nom de la catégorie et le nombre de produits associés à chaque catégorie :
      db.produits.aggregate([
        { $unwind: "$categories" },
        { $group: { _id: "$categories.nom", nombre_de_produits: { $sum: 1 } } },
        { $project: { _id: 0, nom_de_categorie: "$_id", nombre_de_produits: 1 } }
      ])
    • Question 14 Comment puis-je obtenir les produits dont le prix est supérieur à 50 et la quantité est inférieure à 20 ?
      Réponse 14: Utilisez aggregate avec l'opérateur $match pour obtenir les produits dont le prix est supérieur à 50 et la quantité est inférieure à 20 :
      db.produits.aggregate([
        { $match: { $and: [{ prix: { $gt: 50 } }, { quantite: { $lt: 20 } }] } }
      ])
    • Question 15 Comment puis-je obtenir les produits regroupés par mois de promotion avec le prix moyen pour chaque mois ?
      Réponse 15: Utilisez aggregate avec les opérateurs $unwind, $group et $project pour obtenir les produits regroupés par mois de promotion avec le prix moyen pour chaque mois :
      db.produits.aggregate([
        { $unwind: "$moisPromotions" },
        { $group: { _id: "$moisPromotions", prix_moyen: { $avg: "$prix" } } },
        { $project: { _id: 0, moisPromotions: "$_id", prix_moyen: 1 } }
      ])
    • Question 16 Comment puis-je obtenir le nom de la catégorie qui a le plus grand nombre de produits associés ?
      Réponse 16: Utilisez aggregate avec les opérateurs $unwind, $group, $sort et $limit pour obtenir le nom de la catégorie qui a le plus grand nombre de produits associés :
      db.produits.aggregate([
        { $unwind: "$categories" },
        { $group: { _id: "$categories.nom", nombre_de_produits: { $sum: 1 } } },
        { $sort: { nombre_de_produits: -1 } },
        { $limit: 1 }
      ])
    • Question 17 Comment puis-je obtenir les produits triés par marque et par quantité en ordre décroissant ?
      Réponse 17: Utilisez aggregate avec les opérateurs $sort pour obtenir les produits triés par marque et par quantité en ordre décroissant :
      db.produits.aggregate([
        { $sort: { marque: 1, quantite: -1 } }
      ])
    • Question 18 Comment puis-je obtenir les produits triés par mois de promotion en ordre alphabétique, puis par prix en ordre décroissant ?
      Réponse 18: Utilisez aggregate avec les opérateurs $sort pour obtenir les produits triés par mois de promotion en ordre alphabétique, puis par prix en ordre décroissant :
      db.produits.aggregate([
        { $sort: { moisPromotions: 1, prix: -1 } }
      ])
    • Question 20 Comment puis-je obtenir les produits regroupés par marque avec la moyenne des prix pour chaque marque ?
      Réponse 20: Utilisez aggregate avec les opérateurs $group et $project pour obtenir les produits regroupés par marque avec la moyenne des prix pour chaque marque :
      db.produits.aggregate([
        { $group: { _id: "$marque", prix_moyen: { $avg: "$prix" } } },
        { $project: { _id: 0, marque: "$_id", prix_moyen: 1 } }
      ])
    • Question 21 Comment puis-je obtenir la liste des mois de promotion triés par ordre alphabétique, puis par nombre de produits associés en ordre décroissant ?
      Réponse 21: Utilisez aggregate avec les opérateurs $unwind, $group, $sort et $project pour obtenir la liste des mois de promotion triés par ordre alphabétique, puis par nombre de produits associés en ordre décroissant :
      db.produits.aggregate([
        { $unwind: "$moisPromotions" },
        { $group: { _id: "$moisPromotions", nombre_de_produits: { $sum: 1 } } },
        { $sort: { _id: 1, nombre_de_produits: -1 } },
        { $project: { _id: 0, moisPromotions: "$_id", nombre_de_produits: 1 } }
      ])
    • Question 22 Comment puis-je obtenir le nom du fournisseur qui fournit le produit le plus cher ?
      Réponse 22: Utilisez aggregate avec les opérateurs $group, $sort et $limit pour obtenir le nom du fournisseur qui fournit le produit le plus cher :
      db.produits.aggregate([
        { $sort: { prix: -1 } },
        { $limit: 1 },
        { $project: { _id: 0, nom_fournisseur: "$fournisseurs.nom" } }
      ])
    • Question 23 Comment puis-je obtenir la liste des catégories avec le nombre de produits associés à chaque catégorie triés par ordre décroissant de nombre de produits ?
      Réponse 23: Utilisez aggregate avec les opérateurs $unwind, $group, $sort et $project pour obtenir la liste des catégories avec le nombre de produits associés à chaque catégorie triés par ordre décroissant de nombre de produits :
      db.produits.aggregate([
        { $unwind: "$categories" },
        { $group: { _id: "$categories.nom", nombre_de_produits: { $sum: 1 } } },
        { $sort: { nombre_de_produits: -1 } },
        { $project: { _id: 0, nom_categorie: "$_id", nombre_de_produits: 1 } }
      ])
    • Question 24 Comment puis-je obtenir les produits regroupés par mois de promotion avec le prix minimum et maximum pour chaque mois ?
      Réponse 24: Utilisez aggregate avec les opérateurs $unwind, $group et $project pour obtenir les produits regroupés par mois de promotion avec le prix minimum et maximum pour chaque mois :
      db.produits.aggregate([
        { $unwind: "$moisPromotions" },
        { $group: { _id: "$moisPromotions", prix_min: { $min: "$prix" }, prix_max: { $max: "$prix" } } },
        { $project: { _id: 0, moisPromotions: "$_id", prix_minimum: "$prix_min", prix_maximum: "$prix_max" } }
      ])
    • Question 25 Comment puis-je obtenir les produits dont le nom de la catégorie contient le mot "category" ?
      Réponse 25: Utilisez aggregate avec l'opérateur $match et l'opérateur $regex pour obtenir les produits dont le nom de la catégorie contient le mot "category" (en utilisant une expression régulière) :
      db.produits.aggregate([
        { $match: { "categories.nom": { $regex: "category" } } }
      ])