Sujet de TP : MongoDB
S1 2026-2027 - IUT - University de Lille, BUT3 SD
TP MongoDB
Modèle de données & Initialisation
Charger la base de données à partir du fichier tracks.json.
Script d'initialisation (setup_db.py)
Ce script lit le fichier tracks.json présent dans le même dossier et remplit la collection tracks de la base streampulse :
import json
from pymongo import MongoClient
client = MongoClient("mongodb://localhost:27017/")
db = client["streampulse"]
collection = db["tracks"]
# Réinitialisation de la collection pour repartir sur une base propre
collection.drop()
# Chargement du fichier JSON distribué
with open("tracks.json", "r", encoding="utf-8") as f:
sample_data = json.load(f)
collection.insert_many(sample_data)
print(f"Base 'streampulse' initialisée avec {collection.count_documents({})} pistes.")
Partie 1 : Connexion et vérification de l'environnement
Documentation
pymongo.MongoClient(host): Crée un client pour interagir avec le serveur MongoDB.client.server_info(): Renvoie un dictionnaire contenant la version et l'état détaillé du serveur MongoDB.client.list_database_names(): Liste le nom des bases de données présentes sur le serveur.collection.estimated_document_count(): Renvoie une estimation rapide du nombre total de documents d'après les métadonnées de la collection.collection.count_documents(filter): Renvoie le nombre exact de documents correspondant à un critère spécifié.db.list_collection_names(): Renvoie la liste de toutes les collections existantes dans la base de données courante.client.drop_database(name): Supprime l'intégralité d’une base de données sur le serveur.
Exercices
- Initialisation : Place le fichier
tracks.jsondans ton dossier de travail, exécutesetup_db.py, et affiche la liste des bases de données. - Volumétrie : Affiche le nombre total de morceaux importés.
- Comptage filtré : Compte combien de morceaux sont sortis strictly après 2020. (Indice : Tu peux résoudre ceci via une fonction PyMongo de comptage direct ou via une requête de recherche standard dont tu calcules la taille).
- Comptage booléen : Calcule le nombre de pistes marquées comme explicites (
explicit).
Partie 2 : Insertions et Lectures de base
Documentation
cursor.sort(key, direction): Applique un tri croissant (pymongo.ASCENDING) ou décroissant (pymongo.DESCENDING) sur un curseur de résultats.insert_one(doc)/insert_many(docs): Insère un ou plusieurs documents dans la collection.cursor.skip(n): Saute les $n$ premiers résultats renvoyés par la recherche.find_one(filter, projection): Récupère le premier document correspondant au critère sous forme de dictionnaire Python.collection.distinct(key, filter): Renvoie la liste des valeurs uniques d'un champ donné sur l'ensemble de la collection.find(filter, projection): Récupère un curseur itérable sur l'ensemble des documents validant le filtre. La projection spécifie les champs à conserver (1) ou masquer (0).bson.objectid.ObjectId(id_str): Convertit une chaîne hexadécimale en identifiant d'objet natif MongoDB (_id).
Exercices
- Insertion unique : Insère le titre "One More Time" de Daft Punk (
isrc:"FRX99999",year: 2000,duration_sec: 320,metrics:{"plays": 5000000, "likes": 300000},genres:["French Touch", "Disco"],tags:["classic"],explicit: False,comments:[]). Affiche l'ID généré. - Insertion multiple : Insère d'un seul coup 3 nouveaux morceaux de l'artiste "Justice".
- Recherche ponctuelle : Récupère la piste ayant l'ISRC
"FRX00010"et affiche ses données. Que se passe-t-il si tu cherches un ISRC inexistant ? - Recherche avec projection : Affiche la liste des morceaux sortis en 2015. L'affichage ne doit contenir que le titre, l'artiste et l'année (sans le champ
_id). - Recherche conditionnelle (Plusieurs approches possibles) : Récupère uniquement 5 morceaux durant plus de 300 secondes. (Indice : Tu peux limiter le nombre de résultats directement dans ta requête MongoDB ou en utilisant des fonctionnalités natives de Python sur le curseur).
Partie 3 : Requêtes avancées
Documentation
Opérateurs de comparaison :
$gt,$gte,$lt,$lte,$ne,$inOpérateurs d'existence et de type :
$exists,$typeOpérateurs logiques :
$and,$or,$nor,$notOpérateur de recherche textuelle partielle :
$regexOpérateurs de tableaux et objets imbriqués :
$all,$elemMatch,$sizeOpérateur de projection sur tableau :
$slice
Exercices
- Filtres numériques : Trouve toutes les pistes sorties entre 2010 et 2015 (inclus) ayant une durée strictement inférieure à 200 secondes.
- Recherche multi-valeurs : Sélectionne tous les morceaux des artistes "Kavinsky", "Air" ou "Phoenix". (Essaie d'écrire une syntaxe optimisée pour vérifier l'appartenance à un ensemble, puis une alternative avec des conditions disjonctives).
- Combinaisons logiques : Trouve les morceaux qui ont soit plus de 2 000 000 d'écoutes, soit plus de 100 000 likes.
- Combinaison logique complexe : Extrais les morceaux sortis après 2018 ET appartenant soit au genre "Indie Pop", soit au genre "Synthwave".
- Recherche dans un tableau simple : Trouve tous les morceaux possédant à la fois les tags
"night"ET"chill". - Taille de tableau : Trouve les morceaux qui ont exactement 3 tags.
- Tableaux d'objets (Deux méthodes à comparer) :
- Question A : Trouve les pistes avec un commentaire écrit par l'utilisateur
"bob_m"ET ayant une note (rating) de 5. - Question B : Écris cette recherche d'abord de manière naïve (avec un simple filtre par points
comments.useretcomments.rating), puis avec l'opérateur de sous-document strict dédié aux tableaux. Observe la différence sur un document oùbob_mmet la note 2 mais oùalice92met la note 5.
Partie 4 : Mises à jour et Suppressions
Documentation
find_one_and_update(filter, update, return_document=...)/find_one_and_delete(filter): Modifie ou supprime un document de façon atomique et le renvoie.update_one(filter, update)/update_many(filter, update): Modifie un ou plusieurs documents.Opérateurs de modification de champs :
$set,$inc,$unset,$renameOption d'insertion conditionnelle :
upsert=TrueOpérateurs de modification de tableaux :
$push,$addToSet,$pull,$popdelete_one(filter)/delete_many(filter): Supprime un ou plusieurs documents.
Exercices
- Mise à jour ponctuelle de compteurs : Le morceau
"FRX00005"est joué une fois. Incrémente son nombre de lectures de 1 et ajoute 5 likes. - Ajout dans un tableau sans doublon : Ajoute le genre
"Lo-Fi"au morceau"FRX00002". Assure-toi que relancer le script ne crée pas de doublons dans le tableau. - Ajout dans un tableau d'objets : Ajoute un commentaire
{"user": "charlie_p", "text": "Super !", "rating": 5}sur le morceau"FRX00003". - Retrait d'un élément de tableau : Retire le tag
"workout"du morceau"FRX00004". - Mise à jour globale (Plusieurs approches possibles) : Ajoute 10 000 écoutes à toutes les pistes de l'artiste "Daft Punk". (Réalise cette action via une commande Mongo globale, puis envisage comment cela aurait été fait en itérant côté Python).
- Nettoyage : Supprime tous les morceaux ayant strictement moins de 5 000 écoutes.
Partie 5 : Framework d'Agrégation et Indexation
Documentation
collection.list_indexes(): Affiche la liste complète de tous les index enregistrés sur la collection.aggregate(pipeline): Exécute une suite de transformations et traitements ($match, $group,$sort, $unwind,$project, $addFields,$limit, $out,$merge, etc.).🔗 Doc PyMongo : aggregate | 🔗 Doc MongoDB : Aggregation Stages
create_index(keys): Crée un index sur un ou plusieurs champs.collection.drop_index(index_name): Supprime un index spécifique configuré sur la collection.
Exercices
Partie A : Agrégations
- Statistiques globales (Plusieurs approches possibles) : Calcule le nombre total de morceaux par artiste ainsi que leur nombre moyen de likes. Trie du plus populaire au moins populaire. (Résous cela avec le pipeline d'agrégation MongoDB, puis imagine comment le faire en Python avec
find()). - Analyse de tableaux : Calcule le nombre de pistes associées à chaque genre (sachant qu'un morceau a plusieurs genres). Affiche les 3 genres les plus représentés.
- Pipeline complet : Pour les morceaux sortis à partir de 2010, calcule la note moyenne des commentaires reçus par artiste. Affiche le TOP 5 des artistes les mieux notés.
- Durée totale du catalogue par année : Écris un pipeline qui calcule la durée totale d'écoute disponible (en secondes) ainsi que la durée moyenne d'un morceau pour chaque année de sortie (year). Affiche les résultats triés par année croissante.
- Filtre post-agrégation (Artistes prolifiques) : Écris un pipeline d'agrégation qui compte le nombre de morceaux par artiste, puis conserve uniquement les artistes ayant produit au moins 50 morceaux. (Indice : Réfléchis à la place de l'étape de filtrage dans le pipeline).
- Ratio d'engagement par morceau : Crée un pipeline qui ajoute un champ calculé like_rate correspondant au nombre de likes divisé par le nombre d'écoutes (metrics.likes / metrics.plays). Affiche les 5 morceaux ayant le meilleur taux d'engagement.
- Activité des utilisateurs (Commentateurs) : À partir du tableau d'objets comments, identifie les 3 utilisateurs (user) ayant laissé le plus grand nombre de commentaires sur l'ensemble de la plateforme.
Partie B : Performance & Indexation
- Diagnostic sans index : Mesure le temps d'exécution d'une recherche par
isrc(ex:"FRX00250"). Utilise la méthode.explain("executionStats")pour inspecter le nombre de documents scannés (totalDocsExamined) et la stratégie (COLLSCAN). - Optimisation unique : Pose une contrainte d'indexation unique sur
isrc. Relance le diagnostic et compare le résultat (IXSCAN). - Index composé : Crée un index sur l'artiste (croissant) et l'année (décroissant). Teste une requête filtrant sur l'artiste et triant par année. Explicite dans ton rapport la règle des préfixes d'index.