Aller au contenu

MongoDB – Transformations

$arrayElemAt (aggregation)

db.users.aggregate([
   {
     $project:
      {
         name: 1,
         first: { $arrayElemAt: [ "$favorites", 0 ] },  // 0: premier élément
         last: { $arrayElemAt: [ "$favorites", -1 ] }  // -1: dernier élément
      }
   }
])

Documents de la collection users :

{ "_id" : 1, "name" : "dave123", favorites: [ "chocolate", "cake", "butter", "apples" ] }
{ "_id" : 2, "name" : "li", favorites: [ "apples", "pudding", "pie" ] }
{ "_id" : 3, "name" : "ahn", favorites: [ "pears", "pecans", "chocolate", "cherries" ] }
{ "_id" : 4, "name" : "ty", favorites: [ "ice cream" ] }

Exercice

Trouvez le premier score de chaque restaurant.

Équivalent du HAVING de MySQL

db.sales.aggregate(
  [
    // Première étape
    {
      $group :
        { _id : "$item",
          totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } }}
     },
     // Deuxième étape
     {
       $match: { "totalSaleAmount": { $gte: 100 } }
     }
   ]
 )

Regroupement de toutes les données

db.sales.aggregate([
  {
    $group : {
       _id : null,
       totalSaleAmount: { $sum: { $multiply: [ "$price", "$quantity" ] } },
       averageQuantity: { $avg: "$quantity" },
       count: { $sum: 1 }
    }
  }
])

Regroupement par champs multiples

  • On peut regrouper l’information à l’aide de plusieurs champs (index composite).
  • Exemple : Nombre de restaurants par district (borough) et type de cuisine
db.restaurants.aggregate([
    {
        $group:
        {
          _id: {borough: "$borough", cuisine: "$cuisine"},
          nbRestos: { $sum : 1}
        }
    },
    {
        $sort: {_id:1}
   }
])
 { _id: { borough: 'Bronx', cuisine: 'African' }, nbRestos: 31 },
    { _id: { borough: 'Bronx', cuisine: 'American' }, nbRestos: 411 },
    { _id: { borough: 'Bronx', cuisine: 'Armenian' }, nbRestos: 2 },
    { _id: { borough: 'Bronx', cuisine: 'Asian' }, nbRestos: 4 },
    { _id: { borough: 'Bronx', cuisine: 'Bagels/Pretzels' }, nbRestos: 3 },
    { _id: { borough: 'Bronx', cuisine: 'Bakery' }, nbRestos: 71 },
    { _id: { borough: 'Bronx', cuisine: 'Bangladeshi' }, nbRestos: 5 },
    { _id: { borough: 'Bronx', cuisine: 'Barbecue' }, nbRestos: 2 },

Requêtes pivot

db.books.aggregate([
   { $group : { _id : "$author", books: { $push: "$title" } } }
 ])

Documents de départ (collection books) :

{ "_id" : 8751, "title" : "The Banquet", "author" : "Dante", "copies" : 2 },
{ "_id" : 8752, "title" : "Divine Comedy", "author" : "Dante", "copies" : 1 },
{ "_id" : 8645, "title" : "Eclogues", "author" : "Dante", "copies" : 2 },
{ "_id" : 7000, "title" : "The Odyssey", "author" : "Homer", "copies" : 10 },
{ "_id" : 7020, "title" : "Iliad", "author" : "Homer", "copies" : 10 }

Résultat :

{ "_id" : "Homer", "books" : [ "The Odyssey", "Iliad" ] }
{ "_id" : "Dante", "books" : [ "The Banquet", "Divine Comedy", "Eclogues" ] }
  • La requête nous a permis de “pivoter” de documents “livres” (books) vers des documents “auteurs” (authors)
  • La même information est disponible, mais est maintenant centrée sur les auteurs
  • $group avec un $push nous amène d’une relation Many-to-One vers un One-To-Many
  • L’opérateur $unwind permet l’opération contraire :
.aggregate([ { $unwind: "$books" }, { $project: { author: "$_id", title: "$books"} } ])

Tutoriels de MongoDB sur aggregate()

Échantillons de données

  • Voici d’autres échantillons de données fournis par MongoDB que nous utiliserons dans les prochaines semaines :
    • sample_airbnb
    • sample_mflix

Pour accéder aux données :

Utiliser l’environnement cloud et charger le lot de données : https://www.mongodb.com/docs/manual/sample-data/

Chargement des données d’exemple dans Atlas

MongoDB University