Au-delà des bases : commandes de requête MongoDB avancées pour l'analyse de données

Utilisez des filtres, projections et étapes d'agrégation MongoDB avancés pour analyser les données sans les déplacer hors de la base de données.

Au-delà des bases : commandes de requête MongoDB avancées pour l'analyse de données

Les requêtes MongoDB deviennent plus utiles lorsque vous dépassez les simples appels find(). Si vous devez filtrer des documents imbriqués, remodeler la sortie ou calculer des résultats groupés, les opérateurs de requête avancés et les étapes d'agrégation vous permettent d'effectuer ce travail près des données.

Les exemples ci-dessous se concentrent sur des commandes pratiques que vous pouvez exécuter dans mongosh pour le reporting, le dépannage et l'analyse ponctuelle.

Maîtrise du filtrage complexe avec les opérateurs de requête

Alors que la méthode find() de base gère les vérifications d'égalité simples, l'analyse avancée nécessite souvent de combiner plusieurs conditions ou d'interroger des structures de champ spécifiques. MongoDB fournit un ensemble riche d'opérateurs de requête pour construire des filtres granulaires.

Opérateurs logiques pour les requêtes composées

Les opérateurs logiques vous permettent de combiner plusieurs conditions de requête, offrant un contrôle fin sur les documents retournés. Ceux-ci sont essentiels pour structurer des questions analytiques complexes.

  • $and / $and implicite : Utilisé pour spécifier plusieurs critères qui doivent tous être vrais. Bien que souvent implicite (en listant les conditions séquentiellement dans l'objet de requête), $and est nécessaire lorsque vous interrogez le même champ plusieurs fois.
    // $and implicite : Trouver les utilisateurs de plus de 25 ans ET qui vivent à New York
    db.users.find({ age: { $gt: 25 }, city: "New York" });
    
    // $and explicite : Trouver les documents où 'score' > 90 OU 'level' = 5
    db.results.find({ $and: [ { score: { $gt: 90 } }, { level: 5 } ] });
    
  • $or : Sélectionne les documents qui correspondent à n'importe laquelle des expressions spécifiées dans le tableau.
    db.products.find({ $or: [ { category: "Electronics" }, { price: { $lt: 100 } } ] });
    
  • $not : Inverse les résultats de l'expression spécifiée.

Opérateurs géospatiaux et de tableau

Pour les données basées sur la localisation ou les tableaux complexes, des opérateurs spécialisés offrent une puissance analytique :

  • $geoWithin / $near : Essentiel pour trouver des données dans une zone géographique spécifique ou à proximité.
  • $elemMatch : Crucial pour interroger des tableaux de documents imbriqués, garantissant qu'un élément du tableau correspond à tous les critères spécifiés dans $elemMatch.
    // Trouver les commandes où au moins un article dans le tableau 'items' coûte plus de 500 ET a une quantité supérieure à 1
    db.orders.find({ items: { $elemMatch: { price: { $gt: 500 }, qty: { $gt: 1 } } } });
    

Projection avancée : façonner la sortie

La projection, gérée à l'aide du deuxième argument dans la méthode find(), détermine quels champs sont retournés. La projection avancée va au-delà de l'inclusion/exclusion simple pour transformer ou façonner les données retournées.

Exclusion et inclusion de champs

  • 1 inclut un champ ; 0 exclut un champ.
  • Remarque importante : Vous ne pouvez pas mélanger l'inclusion (1) et l'exclusion (0) sauf pour le champ _id (qui est inclus par défaut et peut être explicitement exclu en le définissant à 0).
// Inclure uniquement 'name' et 'email', exclure '_id'
db.users.find({}, { name: 1, email: 1, _id: 0 });

Découpage et manipulation de tableaux

La projection peut limiter le nombre d'éléments de tableau retournés en utilisant $slice :

  • $slice: N : Retourne les N premiers éléments.
  • $slice: -N : Retourne les N derniers éléments.
  • $slice: [M, N] : Retourne N éléments à partir de l'index M.
// Retourner uniquement les 3 dernières entrées du tableau 'history'
db.logs.find({}, { history: { $slice: -3 } });

Analyse des données avec le framework d'agrégation

Le framework d'agrégation MongoDB est l'outil le plus puissant pour l'analyse de données complexes, vous permettant de traiter des enregistrements de données à travers un pipeline d'étapes. Chaque étape effectue une transformation ou une opération spécifique sur les données provenant de l'étape précédente.

Étapes clés d'agrégation

La structure de base utilise db.collection.aggregate([...pipeline]).

1. $match (Filtrage)

Fonctionne de manière similaire à find(), mais est appliqué avant les étapes suivantes, optimisant les performances en réduisant l'ensemble de données tôt.

2. $group (Regroupement et calcul)

Cette étape regroupe les documents par un identifiant spécifié (_id) et applique des opérateurs d'accumulation pour calculer des statistiques récapitulatives.

Accumulateurs courants :

  • $sum
  • $avg
  • $min, $max
  • $push (pour collecter des données de tableau à partir du groupe)
// Calculer le score moyen par département
db.scores.aggregate([
  { $group: { 
    _id: "$department", 
    averageScore: { $avg: "$score" },
    totalStudents: { $sum: 1 }
  } }
]);

3. $project (Remodelage des documents)

Utilisé dans l'agrégation pour remodeler les documents de sortie, un peu comme la projection de find(), mais souvent utilisé pour créer de nouveaux champs calculés.

  • Champs calculés : Vous pouvez effectuer des calculs dans l'étape de projection en utilisant des champs existants.
// Calculer la marge bénéficiaire dans le pipeline
db.sales.aggregate([
  { $project: { 
    _id: 0, 
    productName: 1,
    profit: { $subtract: ["$salePrice", "$cost"] }
  } }
]);

4. $lookup (Jointure de données)

L'étape $lookup ajoute des documents correspondants d'une autre collection, similaire à une jointure externe gauche. Elle est utile lorsque vous devez enrichir des documents pour le reporting sans effectuer la jointure dans le code de l'application.

// Joindre la collection 'orders' avec la collection 'customers'
db.orders.aggregate([
  { $match: { status: "Pending" } },
  { $lookup: {
      from: "customers",         // Collection à joindre
      localField: "customerId",  // Champ des documents d'entrée (orders)
      foreignField: "_id",       // Champ des documents de la collection "from" (customers)
      as: "customerDetails"      // Nom du champ de tableau de sortie
  } }
]);

5. $unwind (Déconstruction de tableaux)

Si un champ de tableau contient plusieurs éléments, $unwind crée un document de sortie séparé pour chaque élément du tableau, dénormalisant efficacement les données pour un regroupement ou un filtrage plus facile sur le contenu du tableau.

Avertissement : $unwind peut augmenter considérablement le nombre de documents. Utilisez-le judicieusement, généralement après $match pour réduire l'ensemble initial.

Meilleures pratiques pour les requêtes analytiques

  1. Indexez les points d'entrée : Indexez les champs utilisés par les premières étapes $match et les étapes $sort basées sur les index. $group peut bénéficier d'un nombre réduit de documents d'entrée, mais il ne devient pas automatiquement rapide simplement parce que le champ groupé a un index.
  2. Filtrez tôt : Placez les étapes $match aussi tôt que possible dans le pipeline d'agrégation. Réduire le nombre de documents tôt économise une puissance de traitement significative pour les étapes ultérieures plus coûteuses comme $lookup ou $group.
  3. Utilisez des types de données appropriés : Assurez-vous que les champs de comparaison (comme les dates ou les valeurs numériques) sont stockés de manière cohérente. Les incompatibilités de type entraînent l'échec silencieux ou inefficace des opérateurs $match.

Utilisez ces commandes lorsque la simple récupération de données ne suffit pas. Commencez par des filtres sélectifs, projetez uniquement les champs dont vous avez besoin, et passez à l'agrégation lorsque vous avez besoin de regroupement, de remodelage ou d'enrichissement entre collections.