Interrogez vos données avec MongoDB

Syntaxe et opérateurs de base

Découvrons maintenant le langage de requête et de manipulation des données dans MongoDB, le MQL (MongoDB Query Language).

Comme nous l’avons vu, MongoDB utilise une syntaxe JSON pour ses opérations de requêtage, articulée autour de deux méthodes principales :

  • find() : Qui retourne un curseur avec tous les documents correspondants

  • findOne() : Qui renvoie le premier document correspondant aux critères

Exemple de requête :

db.restaurants.find({"borough":"Bronx"}) 

Cette requête filtre tous les documents de la collection “restaurants” pour lesquels le “borough” (ce sont des quartiers de la ville de New-York) est le Bronx.

On peut aller plus loin et inclure dans cette requête un opérateur de comparaison pour n’afficher que les établissements ayant reçu un score égale à 10. Score est un paramètre contenu dans une liste de score appelée “grades” dans nos documents :

Exemple de requête :

db.restaurants.find({
          "borough":"Bronx",
          "grades.score" : 10
})

 

La liste des opérateurs de Comparaison de MongoDB est la suivante :

Opérateur

Signification

Exemple d’utilisation

$eq

Égal

{ “grades.score”: { $eq: 10 } }, on a vu juste avant qu’il n’est pas toujours nécessaire de l’utiliser car MongoDB l’interprète par défaut. On l’utilise pour la clarté du code.

$gt

Supérieur

{ “grades.score” : { $gt: 5 } }, recherche les scores supérieurs à 5

$in

Appartenance

{ “borough”: { $in: [“Bronx”, “Manhattan”] } }, recherche les restaurants uniquements dans le Bronx ou à Manhattan

$nin

Exclusion

{ “borough”: { $nin: ["Bronx", "Manhattan"] } }, exclue des résultats les restaurants dans le Bronx ou à Manhattan

Les opérateurs logiques sont également très utiles pour construire vos requêtes. Ils vous permettent de combiner les conditions pour explorer les données.

Liste des opérateurs logiques :

Opérateur

Description

Exemple d'utilisation

$and

Combine plusieurs conditions qui doivent toutes être vraies.

db.restaurants.find({ $and: [ { “borough”: "Bronx" },  { “grades.score”: 10} ] })- Recherche les restaurants du Bronx ayant une note de 10. Idem nous avons vu que cet opérateur n’est pas toujours nécessaire car ici aussi MongoDB cumule les conditions par défaut. On l’utilisera aussi pour la lisibilité du code.

$or

Combine plusieurs conditions, au moins une doit être vraie.

db.restaurants.find({ $or: [ { "grades.score": 10 },  { borough: "Bronx" } ] })- Recherche les restaurants avec un score de 10 ou situés dans le Bronx.

$nor

Combine plusieurs conditions, aucune ne doit être vraie.

db.restaurants.find({ $nor: [ { borough: "Bronx" },  { "grades.grade": "C" } ] })- Recherche les restaurants hors du Bronx et sans une note "C".

$not

Inverse une condition.

db.restaurants.find({ cuisine: { $not: { $eq: "Pizza" } } })- Recherche les restaurants qui ne servent pas de pizza.

$expr

Compare des champs entre eux dans un document.

db.restaurants.find({ $expr: { $gte: [ "$address.building", "1000" ] } })- Recherche les restaurants dont le numéro de bâtiment est supérieur ou égal à 1000.

Filtrer et projeter les données

Nous avons vu comment renvoyer la liste des documents que nous souhaitons sur la base de combinaisons de critères. 

Supprimer les doublons :

Avec l’opérateur $distinct on peut extraire une liste unique (sans doublons) des valeurs d'un champ spécifique d'une collection. C’est très pratique lorsqu’on souhaite obtenir des données dédupliquées pour des analyses ou rapports.

Par exemple pour extraire toutes les cuisines disponibles dans la base de données :

db.restaurants.distinct("cuisine") 

Projeter les données :

L’opération de projection consiste à limiter les champs retournés par notre requête.

Par exemple si je veux dans mes résultats :

  1. le nom des restaurants dans le Bronx et,

  2. le type de cuisine servi par ces restaurants et,

  3. je ne veux pas que l’id du restaurant soit listé (il est projeté par défaut)

Et bien j’utilise la requête suivante :

db.restaurants.find(
  { "borough": "Bronx" },
  { name: 1, cuisine: 1, _id: 0 }
)

 On projette les données pour optimiser les performances en limitant la quantité de données retournées par nos requêtes.

Les expressions régulières ou regex :

Les expressions régulières sont très utiles pour effectuer des recherches en texte libre. 

Par exemple si je veux rechercher les restaurants dont le nom contient "Pizza", j’utilise la requête suivante :

db.restaurants.find({ name: { $regex: /Pizza/i } }) 

En mettant tout cela ensemble on peut créer des requêtes assez complexes ! Voyons cela ensemble dans la vidéo suivante :

À travers cette vidéo j’espère vous avoir fait toucher du doigt quelques différences clés entre les bases de données relationnelles classiques et MongoDB :

Base de données relationnelle 

(ex: MySQL)

Base de données document 

(ex: MongoDB)

Structure des données

Plusieurs tables avec des relations entre elles

Une collection de documents

Modélisation

Schéma rigide et structuré (i.e. les champs sont définis à l’avance)

Schéma flexible (i.e. chaque document peut contenir des champs différents) 

Requêtage

Langage SQL, les requêtes complexes utilisent JOIN pour combiner différentes tables

Requêtes en JSON, souvent plus rapides car nous n’avons pas besoin de jointures entre tables

Créer une séquence d’opérations avec “aggregate”

L'agrégation permet d'exécuter une série d'opérations sur les documents pour transformer ou analyser les données. Ces opérations sont organisées dans un pipeline, où chaque étape effectue une transformation et transmet le résultat à l'étape suivante.

Par exemple, si nous souhaitons calculer le nombre total de restaurants dans chaque quartier, nous pouvons écrire la requête suivante :

db.restaurants.aggregate([
  { $group: { _id: "$borough", totalRestaurants: { $sum: 1 } } }
])

Ici, $groupregroupe les documents par une clé ( $borough) et effectue des calculs comme sum, qui fait la somme.

Le pipeline d'agrégation :

Un pipeline est une série d’étapes exécutées séquentiellement. Chaque étape utilise des opérateurs spécifiques que nous verrons plus tard. La structure générale des pipelines est la suivante :

db.collection.aggregate([
  { étape1 },
  { étape2 },
  { étape3 }
])

 MongoDB propose plusieurs types d'opérateurs utilisés dans l'agrégation, parmi lesquels :

  1. Opérateurs de transformation des documents : Pour remodeler ou enrichir les documents.

    • Exemples :$addFields,$project,$unwind

  2. Opérateurs de calcul : Pour effectuer des calculs mathématiques ou statistiques.

    • Exemples :$sum,$avg,$min,$max,$count

  3. Opérateurs de regroupement : Pour regrouper les documents en catégories basées sur des clés.

    • Exemples : $group

  4. Opérateurs de filtrage : Pour sélectionner les documents selon des critères précis.

    • Exemples :$match,$limit,$sort

Voici quelques utilisations courantes de ces opérateurs

Opérateurs de transformation des documents :

$addFields

  • Description : Ajoute de nouveaux champs ou modifie des champs existants dans chaque document.

  • Exemple d'utilisation : Ajouter un champ montrant si un restaurant a un score parfait dans ses notes :

db.restaurants.aggregate([
  { $addFields: { hasPerfectScore: { $in: [10, "$grades.score"] } } }
])

$project

  • Description : Sélectionne ou exclut certains champs des documents retournés.

  • Exemple d'utilisation : Afficher uniquement le nom et le quartier des restaurants :

db.restaurants.aggregate([
  { $project: { name: 1, borough: 1, _id: 0 } }
])

Opérateurs de calcul :

$sum

  • Description : Calcule la somme des valeurs dans un groupe ou une liste.

  • Exemple d'utilisation : Calculer le nombre total de notes attribuées à chaque restaurant :

db.restaurants.aggregate([
  { $unwind: "$grades" },
  { $group: { _id: "$name", totalScores: { $sum: "$grades.score" } } }
])

$avg

  • Description : Calcule la moyenne des valeurs.

  • Exemple d'utilisation : Trouver la moyenne des scores dans chaque quartier :

db.restaurants.aggregate([
  { $unwind: "$grades" },
  { $group: { _id: "$borough", averageScore: { $avg: "$grades.score" } } }
])

Opérateurs de regroupement :

$group

  • Description : Regroupe les documents par une clé commune et applique des calculs aux groupes.

  • Exemple d'utilisation : Regrouper les restaurants par cuisine et compter le nombre de restaurants par type :

db.restaurants.aggregate([
  { $group: { _id: "$cuisine", totalRestaurants: { $sum: 1 } } }
])

Opérateurs de filtrage :

$match

  • Description : Filtre les documents selon des critères.

  • Exemple d'utilisation : Trouver les restaurants servant de la pizza dans le Bronx :

db.restaurants.aggregate([
  { $match: { borough: "Bronx", cuisine: "Pizza" } }
])

$sort

  • Description : Trie les documents par ordre croissant ou décroissant.

  • Exemple d'utilisation : Trier les restaurants par nom en ordre alphabétique :

db.restaurants.aggregate([
  { $sort: { name: 1 } }
])

L'opérateuraggregateoffre une flexibilité incroyable pour :

  • Filtrer, trier et projeter les données ;

  • Effectuer des calculs complexes comme la somme, la moyenne, ou les ratios ;

  • Remodéliser les données pour répondre à des besoins spécifiques.

Mais attention, l’ordre des opérations est très important (projection après les filtrages, tri sur le résultat d’un groupe, filtrage avant ou après unwind/group…).

Pour aller plus loin sur l’agrégation consultez les liens suivants vers la documentation :

  1. L'agrégation dans MongoDB

  2. Un exemple avec des données géographiques

  3. Un exemple avec des données de préférence utilisateurs

Voyons maintenant comment vous pouvez mettre à jour vos documents dans MongoDB.

Mettre à jour les données

La mise à jour des données dans MongoDB permet de modifier les documents existants selon différents critères. Ces opérations peuvent être effectuées de manière ciblée (modification de champs spécifiques) ou globale (remplacement complet des documents). MongoDB offre une variété d'opérateurs et de méthodes pour gérer efficacement les modifications.

updateOneetupdateMany :

MongoDB propose deux principales méthodes pour mettre à jour les documents. Elles sont utilisées pour modifier des champs spécifiques dans un ou plusieurs documents. Leur syntaxe est la suivante :

db.collection.updateOne(filter, update, options)
db.collection.updateMany(filter, update, options)

Exemple : Modifier le champ cuisine pour un restaurant spécifique :

db.restaurants.updateOne(
  { name: "Tony'S Pizza" },
  { $set: { cuisine: "Italian" } }
)

replaceOne

Utilisé pour remplacer entièrement un document correspondant au filtre. Sa syntaxe est la suivante :

db.collection.replaceOne(filter, replacement, options) 

Exemple : Remplacer un restaurant par un nouveau document :

db.restaurants.replaceOne(
  { name: "Tony'S Pizza" },
  {
    name: "New Pizza Place",
    borough: "Brooklyn",
    cuisine: "Pizza",
    grades: []
  }
)

Opérateurs de mise à jour :

Les opérateurs de mise à jour permettent d'effectuer des modifications précises dans les documents sans les remplacer complètement. Voici leurs principaux cas d’usages :

$set

Utilisé pour modifier ou ajouter des champs.

Exemple : Modifier la rue d'une adresse :

db.restaurants.updateOne(
  { name: "Tony'S Pizza" },
  { $set: { "address.street": "New Street" } }
)

$unset

Utilisé pour supprimer un champ.

Exemple : Supprimer le champ zipcode :

db.restaurants.updateOne(
  { name: "Tony'S Pizza" },
  { $unset: { "address.zipcode": "" } }
)

$inc

Utilisé pour incrémenter ou décrémenter une valeur numérique.

Exemple : Ajouter 1 au score maximal :

db.restaurants.updateOne(
  { name: "Tony'S Pizza" },
  { $inc: { "grades.0.score": 1 } }
) 

$push

Utilisé pour ajouter un élément à un tableau.

Exemple : Ajouter une nouvelle note aux grades :

db.restaurants.updateOne(
  { name: "Tony'S Pizza" },
  { $push: { grades: { grade: "A", score: 10 } } }
)

$pull

Utilisé pour retirer un élément spécifique d'un tableau.

Exemple : Supprimer les scores de  du tableau grades :

db.restaurants.updateMany(
  { name: "Tony'S Pizza" },
  { $pull: { grades: { score: 2 } } }
)

$deleteOne

Utilisé pour supprimer un seul document correspondant au filtre spécifié. Si plusieurs documents correspondent au filtre, seul le premier trouvé sera supprimé.

Exemple d'utilisation : Supprimer un restaurant par son nom :

db.restaurants.deleteOne({ name: "Tony'S Pizza" })

$deleteMany

Utilisé pour supprimer tous les documents correspondant au filtre spécifié. Elle est idéale pour des suppressions en masse.

Exemple d'utilisation : Supprimer les restaurants avec une cuisine indéfinie :

db.restaurants.deleteMany({ cuisine: null }) 

Gestion des modifications de documents :

Lorsqu’on modifie les documents, il existe une stratégie bien utile pour éviter des erreurs et garantir la cohérence des données :

Le paramètreupsertvous permet de créer un nouveau document si aucun document ne correspond au filtre.

db.restaurants.updateOne(
  { name: "Nonexistent Restaurant" },
  { $set: { borough: "Manhattan", cuisine: "Sushi" } },
  { upsert: true }
)

Vérifiez toujours la validation des mises à jour !

Voilà nous avons fait un tour assez complet des opérateurs disponibles dans MongoDB pour mettre à jour vos données. Je vous conseille de prendre le réflexe de vérifier les données avant et après la mise à jour pour s'assurer que les modifications sont correctes :

  • UtiliserfindOnepour inspecter un document avant la modification.

  • Utiliserfind ouaggregatepour des validations après mise à jour.

À vous de jouer !

À vous de mobiliser ces opérateurs maintenant pour réaliser les opérations suivantes !

Étape 1 : Rechercher des données

Utilisez la méthode find() pour répondre aux questions suivantes :

  1. Trouvez tous les restaurants du Bronx servant de la pizza.

  2. Listez uniquement les noms et les cuisines des restaurants situés dans le Bronx avec une projection.

Étape 2 : Filtrer et projeter les données

Réalisez des filtrages avancés et testez les opérateurs :

  1. Trouvez les restaurants ayant reçu une note supérieure ou égale à 20.

  2. Projetez uniquement les champs name, borough et le premier score des grades.

Étape 3 : Manipuler les données avec le pipeline d’agrégation

Mettez en place une séquence d’opérations pour répondre aux questions suivantes :

  1. Affichez le nombre de restaurants par quartier.

  2. Calculez la moyenne des scores des restaurants pour chaque quartier. 

Étape 4 : Mettre à jour les données

Utilisez les méthodes de mise à jour pour modifier les documents :

  1. Ajoutez un nouveau champ specialOffer à tous les restaurants servant de la pizza.

  2. Incrémentez le score maximal des restaurants dont le nom contient "Pizza" de 5 points.

Une fois l’activité terminée, vérifiez votre travail en le comparant avec cette solution.

En résumé 

  • Findest utilisé pour rechercher des documents correspondant à un filtre.

  • Les opérateurs de requêtes incluent $eq$gte,$regex et $elemMatch.

  • Les méthodes d'agrégation commeaggregatepermettent d'enchaîner des transformations.

  • Utilisez la projection$projectpour contrôler les champs visibles dans les résultats.

  • Les mises à jour peuvent être appliquées avec updateOneupdateMany  oureplaceOne 

Conclusion du cours

Après avoir testé votre compréhension de la partie 2 avec le quiz qui suit, vous aurez terminé ce cours d’introduction au NoSQL et à MongoDB sera déjà fini…

Mais ce n’est que le début de votre apprentissage ! Continuez à nourrir votre curiosité et à approfondir vos connaissances sur MongoDB et l'univers des bases de données NoSQL. Maîtriser ces technologies est aujourd’hui incontournable dans l’univers de la data et MongoDB est un excellent point de départ. Je vous recommande de suivre les contenus de formation de l’Université MongoDB. Les parcours sont bien structurés et régulièrement mis à jour, par exemple récemment avec des contenus pour vous aider à créer des projets dans lesquels vous utilisez des LLM (ex: ChatGPT, etc.) pour lire vos données dans une base MongoDB.

AD_4nXfAjyErIBIUS5_2rWWvrgHIgDO4BDn2zB_ULDAF87T1nhAc0ypU2BslU178uCRivR9QOtgJZsT_tY9nLpAhznHIWYi2qQFV1IzGlmRBNyC39ftmcmL_a5kapSISV-9ALqGZ8cX-fA?key=7n72Od3YUxXHWa8QCk8BOCNK
Le parcours en ligne sur l’Université MongoDB

Travailler avec MongoDB vous permettra d’aller loin, mais MongoDB n’est qu’une fraction de la richesse et de la diversité des solutions NoSQL existantes. Explorer d'autres bases de données NoSQL, comme Cassandra, Neo4j ou Redis, vous permettra de mieux comprendre leurs forces et leurs spécificités.

Pour rester à jour, pensez à consulter régulièrement des ressources comme DB-Engines pour suivre les tendances et les évolutions des différentes bases de données. Si vous êtes avides de tutoriels et d'analyses approfondies, des sites comme Medium et Dev.to regorgent de contenu publié par des experts et des passionnés. Enfin, je vous encourage à participer à des Meet-ups pour échanger avec d'autres professionnels et découvrir des cas d'usage concrets.

Que la force soit avec vous ! 🙂

Ever considered an OpenClassrooms diploma?
  • Up to 100% of your training program funded
  • Flexible start date
  • Career-focused projects
  • Individual mentoring
Find the training program and funding option that suits you best