Interroger les tableaux MongoDB

MongoDBBeginner
Pratiquer maintenant

Introduction

Dans ce laboratoire, vous apprendrez à interroger efficacement les tableaux (arrays) dans MongoDB. Les tableaux sont une structure de données fondamentale dans MongoDB, vous permettant de stocker des listes de valeurs au sein d'un champ de document unique. Ce laboratoire vous guidera à travers les techniques essentielles pour travailler avec des données de tableaux, de la correspondance d'éléments simple à des requêtes plus complexes utilisant des opérateurs spécialisés. Vous apprendrez à trouver des documents en fonction du contenu, de la taille et de la position des éléments dans les tableaux, ce qui sont des compétences cruciales pour tout développeur travaillant avec MongoDB.

Démarrage et correspondance d'éléments de tableau de base

Dans cette première étape, vous vous connecterez au serveur MongoDB, créerez une base de données et insérerez des données d'exemple. Ensuite, vous effectuerez des requêtes de base pour trouver des documents en faisant correspondre des éléments dans un tableau.

Tout d'abord, ouvrez le shell MongoDB (mongosh) pour interagir avec votre base de données. Cette commande vous connectera à l'instance MongoDB en cours d'exécution.

mongosh

Une fois dans le shell, vous verrez une invite test>. Passons à une nouvelle base de données nommée arraylab. La commande use crée la base de données si elle n'existe pas déjà et y bascule le contexte actuel.

use arraylab

Maintenant, insérons quelques documents dans une nouvelle collection appelée products. Chaque document représente un produit et contient deux champs de type tableau (array) : tags et colors. Copiez et collez la commande suivante dans votre shell :

db.products.insertMany([
  {
    name: "Laptop",
    tags: ["electronics", "computer", "work"],
    colors: ["silver", "black", "blue"]
  },
  {
    name: "Smartphone",
    tags: ["electronics", "mobile", "communication"],
    colors: ["red", "blue", "green"]
  },
  {
    name: "Headphones",
    tags: ["electronics", "audio", "music"],
    colors: ["black", "white"]
  }
]);

Pour trouver un document qui contient un élément spécifique dans un tableau, vous pouvez interroger directement cette valeur. Cette requête trouve tous les produits qui ont le tag "mobile".

db.products.find({ tags: "mobile" });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Smartphone',
    tags: [ 'electronics', 'mobile', 'communication' ],
    colors: [ 'red', 'blue', 'green' ]
  }
]

Vous pouvez également trouver des documents dont le tableau correspond à une séquence exacte d'éléments. Cette requête trouve le produit dont le tableau tags est exactement ["electronics", "computer", "work"] dans cet ordre spécifique.

db.products.find({ tags: ["electronics", "computer", "work"] });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Vous pouvez rester dans le shell mongosh pour les étapes suivantes. Pour quitter le shell à tout moment, tapez exit et appuyez sur Entrée.

Utilisation des opérateurs de requête sur tableaux $all et $in

La correspondance simple est utile, mais MongoDB fournit des opérateurs puissants pour des requêtes sur tableaux plus complexes. Dans cette étape, vous apprendrez à utiliser $all pour faire correspondre plusieurs éléments indépendamment de leur ordre, et $in pour faire correspondre n'importe lequel d'une liste d'éléments.

Nous continuerons à utiliser la collection products de l'étape précédente.

L'opérateur $all sélectionne les documents où le champ tableau contient tous les éléments spécifiés. L'ordre des éléments dans la requête n'a pas d'importance. Trouvons les produits disponibles à la fois en "bleu" et en "argent".

db.products.find({ colors: { $all: ["blue", "silver"] } });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

L'opérateur $in sélectionne les documents où le champ tableau contient au moins une des valeurs spécifiées. Il agit comme une condition "OU" pour les éléments du tableau. Trouvons les produits qui ont soit le tag "music", soit le tag "work".

db.products.find({ tags: { $in: ["music", "work"] } });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Ces opérateurs offrent beaucoup plus de flexibilité lors de la recherche de documents basés sur le contenu de leurs tableaux.

Interrogation par taille et position de tableau

Parfois, le nombre d'éléments dans un tableau ou la position d'un élément spécifique est important. Cette étape explique comment interroger en fonction de la taille du tableau à l'aide de l'opérateur $size et par position d'élément à l'aide de la notation par points.

L'opérateur $size sélectionne les documents qui ont un tableau avec un nombre spécifique d'éléments. Trouvons les produits qui ont exactement deux couleurs disponibles.

db.products.find({ colors: { $size: 2 } });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Pour interroger un élément à une position spécifique (index) dans un tableau, vous utilisez la notation par points au format "nomChamp.index". N'oubliez pas que les index de tableau commencent à zéro, donc le premier élément est à l'index 0. Cette requête trouve tous les produits où le premier élément du tableau tags est "electronics".

db.products.find({ "tags.0": "electronics" });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Smartphone',
    tags: [ 'electronics', 'mobile', 'communication' ],
    colors: [ 'red', 'blue', 'green' ]
  },
  {
    _id: ObjectId("..."),
    name: 'Headphones',
    tags: [ 'electronics', 'audio', 'music' ],
    colors: [ 'black', 'white' ]
  }
]

Maintenant, trouvons un produit où la deuxième couleur (index 1) est "black".

db.products.find({ "colors.1": "black" });

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    colors: [ 'silver', 'black', 'blue' ]
  }
]

Interrogation de tableaux de documents embarqués

Un schéma courant et puissant dans MongoDB consiste à avoir des tableaux contenant d'autres documents. Ceux-ci sont connus sous le nom de documents embarqués ou imbriqués. L'interrogation de ceux-ci nécessite un opérateur spécial, $elemMatch, pour s'assurer que toutes les conditions s'appliquent au même élément du tableau.

Tout d'abord, ajoutons de nouveaux produits qui ont un tableau specs. Chaque élément du tableau specs est un document avec les champs ram, storage et price.

db.products.insertMany([
  {
    name: "Gaming Laptop",
    tags: ["electronics", "computer", "gaming"],
    specs: [
      { ram: 16, storage: 512, price: 1200 },
      { ram: 32, storage: 1024, price: 2000 }
    ]
  },
  {
    name: "Office Laptop",
    tags: ["electronics", "computer", "work"],
    specs: [
      { ram: 8, storage: 256, price: 600 },
      { ram: 16, storage: 512, price: 800 }
    ]
  }
]);

Maintenant, supposons que nous voulions trouver un ordinateur portable qui a une configuration avec au moins 16 Go de RAM et un prix inférieur à 1000 $. Une requête simple pourrait sembler correcte mais peut conduire à de mauvais résultats. Par exemple, db.products.find({ "specs.ram": { $gte: 16 }, "specs.price": { $lt: 1000 } }) correspondrait à un document si un document embarqué a suffisamment de RAM et qu'un autre a un prix suffisamment bas.

Pour s'assurer qu'un seul document embarqué dans le tableau satisfait toutes les conditions, vous devez utiliser l'opérateur $elemMatch.

db.products.find({
  specs: {
    $elemMatch: { ram: { $gte: 16 }, price: { $lt: 1000 } }
  }
});

Cette requête trouve correctement uniquement l'"Office Laptop", car il possède un élément de spécification { ram: 16, storage: 512, price: 800 } qui répond aux deux conditions simultanément.

Exemple de sortie :

[
  {
    _id: ObjectId("..."),
    name: 'Office Laptop',
    tags: [ 'electronics', 'computer', 'work' ],
    specs: [
      { ram: 8, storage: 256, price: 600 },
      { ram: 16, storage: 512, price: 800 }
    ]
  }
]

Projection de champs de tableaux

Souvent, vous n'avez pas besoin que le document entier soit renvoyé par une requête. La projection vous permet de spécifier quels champs inclure ou exclure. Pour les tableaux, MongoDB fournit des opérateurs de projection spéciaux comme $slice pour contrôler quels éléments du tableau sont renvoyés.

L'opérateur de projection $slice renvoie un sous-ensemble d'un tableau. Vous pouvez spécifier un nombre positif pour obtenir les N premiers éléments, ou un nombre négatif pour obtenir les N derniers éléments.

Récupérons tous les produits mais ne renvoyons que le name et les deux premiers tags pour chacun d'eux. Le premier argument de find, {}, est un document de requête vide qui correspond à tous les documents. Le second argument est le document de projection. Nous utilisons _id: 0 pour exclure le champ _id par défaut.

db.products.find({}, { name: 1, tags: { $slice: 2 }, _id: 0 });

Exemple de sortie :

[
  { "name": "Laptop", "tags": ["electronics", "computer"] },
  { "name": "Smartphone", "tags": ["electronics", "mobile"] },
  { "name": "Headphones", "tags": ["electronics", "audio"] },
  { "name": "Gaming Laptop", "tags": ["electronics", "computer"] },
  { "name": "Office Laptop", "tags": ["electronics", "computer"] }
]

Un autre opérateur de projection utile est l'opérateur positionnel $. Lorsque vous interrogez un tableau, cet opérateur garantit que seul le premier élément qui correspond à la condition de requête est renvoyé dans le champ de tableau projeté.

Trouvons les produits avec le tag "mobile" et renvoyons uniquement le name et ce tag correspondant spécifique du tableau tags.

db.products.find({ tags: "mobile" }, { name: 1, "tags.$": 1, _id: 0 });

Exemple de sortie :

[{ "name": "Smartphone", "tags": ["mobile"] }]

Ceci est très efficace pour récupérer uniquement les parties pertinentes d'un grand tableau sans avoir à traiter le tableau complet dans votre application.

Résumé

Dans ce laboratoire, vous avez appris les techniques fondamentales pour interroger des tableaux dans MongoDB. Vous avez commencé par la correspondance d'éléments de base et êtes passé à l'utilisation d'opérateurs de tableau puissants tels que $all, $in et $size. Vous avez également exploré comment interroger par la position d'un élément et comment interroger correctement des tableaux de documents embarqués en utilisant $elemMatch. Enfin, vous avez appris à façonner la sortie de vos requêtes en projetant des éléments de tableau spécifiques à l'aide de $slice et de l'opérateur positionnel $. Ces compétences sont essentielles pour gérer et récupérer efficacement des données à partir de structures de documents complexes dans MongoDB.