Dans toute entreprise, les données sont votre plus grand atout. En analysant les données, vous pouvez prendre des décisions sur les tendances et la prédiction du comportement des clients. Cela permet d’accroître la rentabilité de l’entreprise et de prendre des décisions efficaces.

Sans logiciel de base de données, une tâche simple comme trouver la moyenne de toutes les valeurs dans un système rempli d’enregistrements serait fastidieuse. Heureusement, les bases de données ont rendu l’analyse des données plus facile et plus rapide grâce aux fonctions et aux opérateurs.

Cet article vous éclairera sur les opérateurs utilisés dans le logiciel de base de données MongoDB.

Que sont les opérateurs MongoDB ?

MongoDB est un logiciel de base de données NoSQL qui gère des informations orientées documents.

L’une des principales caractéristiques de MongoDB est sa rapidité. Pour renvoyer les requêtes plus rapidement, MongoDB peut utiliser des opérateurs pour exécuter des fonctions spécifiques.

Les opérateurs sont des symboles spéciaux qui aident les compilateurs à effectuer des tâches mathématiques ou logiques. MongoDB propose plusieurs types d’opérateurs pour interagir avec la base de données.

Types d’opérateurs MongoDB

Il existe neuf types d’opérateurs, chacun nommé en fonction de sa fonction. Par exemple, les opérateurs logiques utilisent des opérations logiques. Pour les exécuter, vous devez utiliser un mot-clé spécifique et respecter les syntaxes. Cependant, elles sont assez faciles à suivre !

À la fin de cet article, vous serez en mesure d’apprendre les bases de chaque opérateur et de ses fonctions.

Opérateurs logiques

Les opérateurs logiques sont souvent utilisés pour filtrer les données en fonction des conditions données. Ils permettent également l’évaluation de nombreuses conditions, que nous aborderons plus en détail.

Vous trouverez ci-dessous quelques opérateurs logiques que vous pouvez utiliser :

$and

Une condition « and » effectue une opération logique « and » sur un tableau de deux ou plusieurs expressions. Elle sélectionne les documents pour lesquels toutes les conditions des expressions sont satisfaites.

Il s’agit de la syntaxe standard de l’expression $and:

{ $and: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }
db.inventory.find( { $and: [ { quantity: { $lt: 15 } }, { price: 10 } ] } )

$or

Une condition « ou » effectue une opération logique « ou » sur un tableau de deux expressions ou plus. Elle sélectionne les documents pour lesquels au moins une des expressions est vraie.

Voici la syntaxe standard de l’expression $or:

{ $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }.

Par exemple, si nous voulons sélectionner les documents où le prix est de 10 $ ou la quantité est inférieure à 15, nous pouvons saisir la requête suivante :

db.inventory.find( { $or: [ { quantity: { $lt: 15 } }, { price: 10 } ] } )

Nous ne sommes pas obligés de limiter l’expression à deux critères – nous pouvons en ajouter d’autres. Par exemple, la requête ci-dessous sélectionne les documents dont le prix est égal à 10 $, la quantité est inférieure à 15, ou le tag est « stationary » :

db.inventory.find( { $or: [ { quantity: { $lt: 15 } }, { price: 10 }, { tag: "stationary" }] } )

Lors de l’exécution de ces clauses, MongoDB effectue soit une analyse de collection, soit une analyse d’index. Si tous les index prennent en charge les clauses, alors MongoDB utilise les index pour vérifier une expression $or. Sinon, il utilise une analyse de collection à la place.

Mais si vous voulez tester les critères dans le même champ, vous pouvez utiliser l’opérateur $in plutôt que l’opérateur $or. Par exemple, si vous voulez une collection de documents dont la quantité est soit 10 soit 20, vous devrez peut-être exécuter la requête $in ci-dessous à la place :

db.inventory.find ( { quantity: { $in: [20, 50] } } )

Nous reviendrons plus tard sur l’opérateur $in.

$nor

Cet opérateur effectue une opération logique « nor » sur un tableau en utilisant une ou plusieurs expressions. Ensuite, il sélectionne les documents qui ne répondent pas aux expressions de la requête. En termes plus simples, il fait l’inverse de la condition $or.

Voici la syntaxe générale :

{ $nor: [ { <expression1> }, { <expression2> }, ...  { <expressionN> } ] }

Considérons la requête suivante :

db.inventory.find( { $nor: [ { price: 3.99 }, { sale: true } ]  } )

Cette requête sélectionne les documents qui contiennent :

  • une valeur de champ « price » non égale à 3,99 $, et une valeur « sale » non égale à true ; ou
  • un champ « price » dont la valeur n’est pas égale à 3,99 $, et un champ « sale » vide ou absent ; ou
  • aucun champ « price », et un champ « sale » non égal à true ; ou
  • ni champ « price » ni champ « sale » renseignés ou présents.

$not

Cet opérateur effectue une opération logique « not » sur un tableau pour l’expression spécifiée. Il sélectionne ensuite les documents qui ne correspondent pas aux expressions de la requête. Cela inclut les documents qui ne contiennent pas le champ.

Voici la syntaxe générale :

{ field: { $not: { <operator-expression> } } }

Par exemple, prenez la requête suivante :

db.inventory.find( { price: { $not: { $lt: 3.99 } } } )

Cette requête sélectionnerait les documents qui contiennent :

  • un champ « price » dont la valeur est supérieure ou égale à 3,99 $ ; et
  • un champ « price » non renseigné ou inexistant.

Opérateurs de comparaison

Les opérateurs de comparaison peuvent être utilisés pour comparer des valeurs dans un ou plusieurs documents.

Vous trouverez ci-dessous un exemple de code d’une simple collection d’inventaire pour un supermarché :

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] },
{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] },
{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] },
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] },
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] },
{ _id: 6, item: { name: "strawberry", code: "123" }, tags: [ "B" ] }

Nous allons utiliser cet exemple tout en détaillant ensuite chaque opérateur de comparaison.

Égal à ($eq)

Cet opérateur correspond aux valeurs qui sont égales à la valeur donnée :

{ <field>: { $eq: <value> } }

Par exemple, si nous voulons récupérer un document spécifique de la collection d’inventaire ayant la valeur exacte de quantité « 20 », nous saisirions la commande suivante :

db.inventory.find( { qty: { $eq: 20 } } )

La requête renverrait ce qui suit :

{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] }, 
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

Supérieur à ($gt)

Cet opérateur correspond si les valeurs sont supérieures à la valeur donnée :

{ field: { $gt: value } }

Dans cet exemple, nous récupérons les documents dont la quantité est supérieure à 15 :

db.inventory.find({"qty": { $gt: 15}})

La requête renverrait ce qui suit :

{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] }
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

Inférieur à ($lt)

Cet opérateur correspond aux valeurs qui sont inférieures à la valeur fournie :

{ field: { $lt: value } }

Trouvons les documents dont la quantité est inférieure à 25 :

db.inventory.find({"qty": { $lt: 25}})

La requête retournerait ce qui suit :

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

Supérieur ou égal à ($gte)

Cet opérateur correspond lorsque les valeurs sont supérieures ou égales à la valeur donnée :

{ field: { $gte: value } }

Dans cet exemple, nous récupérons les documents dont la quantité est supérieure ou égale à 25 :

db.inventory.find({"qty": { $gte: 25}})

Cette requête retournerait ce qui suit :

{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] }

Inférieur ou égal à ($lte)

Cet opérateur ne correspond que si les valeurs sont inférieures ou égales à la valeur donnée :

{ field: { $lte: value } }

Trouvons les documents dont la quantité est inférieure ou égale à 25.

db.inventory.find({"qty": { $lte: 25}})

Nous pouvons nous attendre à ce que cette requête renvoie ce qui suit :

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "banana", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 5, item: { name: "pears", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }

Dans ($in)

Cet opérateur renvoie les documents qui correspondent aux valeurs spécifiées :

{ field: { $in: [<value1>, <value2>, ... <valueN> ] } }

La valeur d’un champ est égale à toute valeur du tableau spécifié. Pour récupérer les documents ayant les valeurs « 30 » et « 15 » dans la collection d’inventaire, par exemple, vous feriez ceci :

db.inventory.find({ "qty": { $in: [30, 15]}})

La sortie serait :

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] }

Pas dans ($nin)

Cet opérateur renvoie les documents qui ne correspondent pas aux valeurs données. Voici la syntaxe de base de l’opérateur $nin:

{ field: { $nin: [ <value1>, <value2> ... <valueN> ]

$nin sélectionne les documents où :

  • la valeur du champ ne se trouve pas dans le tableau spécifié ; ou
  • le champ n’existe pas.

Si le champ contient des tableaux, il sélectionnera les tableaux où aucun élément spécifié dans la section valeur n’est présent. Par exemple, nous voulons sélectionner les documents dont la quantité n’est égale ni à 20 ni à 15.

En outre, elle correspond également aux documents qui ne possèdent pas de champ de quantité :

db.inventory.find({ "qty": { $nin: [ 20, 15 ]}})

Le résultat serait le suivant :

{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] }
{ _id: 6, item: { name: "strawberry", code: "123" }, tags: [ "B" ] }

Non égal ($ne)

L’opérateur $ne renvoie les documents où la valeur spécifiée n’est pas égale :

{ $ne: value } }

Par exemple, disons que nous voulons sélectionner tous les documents où la quantité n’est pas égale à 20 :

db.inventory.find( { qty: { $ne: 20 } } )

La sortie serait :

{ _id: 1, item: { name: "apple", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 3, item: { name: "spinach", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "lentils", code: "456" }, qty: 30, tags: [ "B", "A" ] }
{ _id: 6, item: { name: "strawberry", code: "123" }, tags: [ "B" ] }

D’après le résultat ci-dessus, nous pouvons voir que la requête sélectionnera les documents qui n’ont pas de champ de quantité.

Opérateurs d’éléments

Les opérateurs de requête par élément permettent d’identifier des documents à l’aide des champs du document. Les opérateurs d’éléments se composent de $exist et $type.

$exists

Cet opérateur correspond aux documents qui possèdent un champ spécifié. Cet opérateur a une valeur booléenne qui peut être soit true soit false.

S’il est spécifié comme étant true, il correspond aux documents qui contiennent ce champ, y compris les documents où la valeur du champ est nulle. Si <boolean> est false, alors la requête renvoie uniquement les documents qui ne contiennent pas le champ.

Voici la syntaxe standard :

{ field: { $exists: <boolean> } } )

Prenons un exemple où nous avons une collection de données pour un tableau nommé « bagofmarbles », où chaque sac contient des billes de différentes couleurs :

{ red: 5, green: 5, blue: null }
{ red: 3, green: null, blue: 8 }
{ red: null, green: 3, blue: 9 }
{ red: 1, green: 2, blue: 3 }
{ red: 2, blue: 5 }
{ red: 3, green: 2 }
{ red: 4 }
{ green: 2, blue: 4 }
{ green: 2 }
{ blue: 6 }

Disons que nous voulons une requête qui renvoie uniquement les sacs où les billes rouges existent. Cela signifie que nous devrions entrer la valeur booléenne comme true. Voyons cela :

db.bagofmarbles.find( { red: { $exists: true } } )

Les résultats seront constitués des documents qui contiennent le champ « red », même si la valeur est null. Cependant, ils ne seront pas constitués des documents où le champ « red » n’existe pas :

{ red: 5, green: 5, blue: null }
{ red: 3, green: null, blue: 8 }
{ red: null, green: 3, blue: 9 }
{ red: 1, green: 2, blue: 3 }
{ red: 2, blue: 5 }
{ red: 3, green: 2 }
{ red: 4 }

Si nous ne voulions que les sacs où les billes rouges n’existent même pas comme champ, nous pouvons entrer la requête ci-dessous :

db.bagofmarbles.find( { red: { $exists: false} )

Les résultats seraient constitués des documents qui ne contiennent pas le champ « red » :

{ green: 2, blue: 4 }
{ green: 2 }
{ blue: 6 }

$type

Cet opérateur fait correspondre les documents en fonction du type de champ spécifié. Il est utile lorsque vous avez des données très peu structurées, ou lorsque les types de données ne sont pas prévisibles. Ces types de champ sont des types BSON spécifiés et peuvent être définis par un numéro de type ou un alias.

Voici la syntaxe générale de $type:

{ field: { $type: <BSON type> } }

Disons que nous avons un carnet d’adresses contenant les documents ci-dessous :

db={
  addressBook: [
    {
      "_id": 1,
      address: "2100 Jupiter Spot",
      zipCode: "9036325"
    },
    {
      "_id": 2,
      address: "25 Moon Place",
      zipCode: 26237
    },
    {
      "_id": 3,
      address: "2324 Neptune Ring",
      zipCode: NumberLong(77622222)
    },
    {
      "_id": 4,
      address: "33 Saturns Moon",
      zipCode: NumberInt(117)
    },
    {
      "_id": 5,
      address: "1044 Venus Lane",
      zipCode: [
        "99883637232",
        "73488976234"
      ]
    }
  ]
}

En observant les documents ci-dessus, le code postal a différents types de données. Il s’agit de valeurs longues, doubles, entières et de chaînes de caractères.

Si nous voulons seulement les documents qui ont un type de données spécifié comme le code postal – prenons une chaîne de caractères pour cet exemple – nous devrions saisir la requête suivante dans le compilateur :

db.addressBook.find({
  "zipCode": {
    $type: "string"
  }
})

Cela retournerait les documents suivants :

[
  {
    "_id": 1,
    "address": "2100 Jupiter Spot",
    "zipCode": "9036325"
  },
  {
    "_id": 5,
    "address": "1044 Venus Lane",
    "zipCode": [
      "99883637232",
      "73488976234"
    ]
  }
]

En outre, il existe un type « number », qui inclut toutes les valeurs longues, entières ou doubles sous forme de tableau contenant un élément des types spécifiés :

db.addressBook.find( { "zipCode" : { $type : "number" } } )

Sortie :

[
{
      "_id": 2,
      address: "25 Moon Place",
      zipCode: 26237
    },
    {
      "_id": 3,
      address: "2324 Neptune Ring",
      zipCode: NumberLong(77622222)
    },
    {
      "_id": 4,
      address: "33 Saturns Moon",
      zipCode: NumberInt(117)
    }
]

Si les documents ont un type de tableau, l’opérateur $type renvoie les documents dans lesquels au moins un élément de tableau correspond au type passé à l’opérateur.

Opérateurs de tableau

MongoDB comprend également des opérateurs de tableau, pour interroger des documents contenant des tableaux.

Il existe trois opérateurs principaux : $all, $elemMatch et $size. Nous allons examiner chacun d’eux en détail ci-dessous.

tout

L’opérateur $all sélectionne les documents dans lesquels la valeur d’un champ est un tableau contenant les éléments spécifiés :

{ : { $all: [ <value1> , <value2> ... ] } }

Par exemple, disons que nous avons une collection de documents pour un magasin de vêtements, avec les éléments suivants dans l’inventaire.

{
   _id: ObjectId("5234cc89687ea597eabee675"),
   code: "shirt",
   tags: [ "sale", "shirt", "button", "y2k", "casual" ],
   qty: [
          { size: "S", num: 10, color: "blue" },
          { size: "M", num: 45, color: "blue" },
          { size: "L", num: 100, color: "green" }
        ]
},

{
   _id: ObjectId("5234cc8a687ea597eabee676"),
   code: "pant",
   tags: [ "y2k", "trendy", "shine" ],
   qty: [
          { size: "6", num: 100, color: "green" },
          { size: "6", num: 50, color: "blue" },
          { size: "8", num: 100, color: "brown" }
        ]
},

{
   _id: ObjectId("5234ccb7687ea597eabee677"),
   code: "pant2",
   tags: [ "trendy", "shine" ],
   qty: [
          { size: "S", num: 10, color: "blue" },
          { size: "M", num: 100, color: "blue" },
          { size: "L", num: 100, color: "green" }
        ]
},

{
   _id: ObjectId("52350353b2eff1353b349de9"),
   code: "shirt2",
   tags: [ "y2k", "trendy" ],
   qty: [
          { size: "M", num: 100, color: "green" }
        ]
}

Nous voudrions récupérer tous les documents (dans ce cas, les vêtements) de l’inventaire qui sont liés aux tags « trendy » et « y2k ». La requête ci-dessous utilise l’opérateur $all où la valeur du champ tags est un tableau dont les éléments incluent « y2k » et « trendy » :

db.inventory.find( { tags: { $all: [ "y2k", "trendy" ] } } )

La requête ci-dessus renvoie ce qui suit :

{
   _id: ObjectId("5234cc8a687ea597eabee676"),
   code: "pant",
   tags: [ "y2k", "trendy", "shine" ],
   qty: [
          { size: "6", num: 100, color: "green" },
          { size: "6", num: 50, color: "blue" },
          { size: "8", num: 100, color: "brown" }
        ]
}

{
   _id: ObjectId("52350353b2eff1353b349de9"),
   code: "shirt2",
   tags: [ "y2k", "trendy" ],
   qty: [
          { size: "M", num: 100, color: "green" }
        ]
}

À partir de l’exemple ci-dessus, nous constatons également que l’opérateur $all exécute simplement la même fonction que l’opération $and.

Alternativement, nous pourrions utiliser la requête ci-dessous qui donnerait un résultat similaire à celui ci-dessus :

db.inventory.find({
  $and: [
    {
      tags: "y2k"
    },
    {
      tags: "trendy"
    }
  ]
})

$elemMatch

L’opérateur $elemMatch correspond aux documents qui contiennent un champ de tableau dont au moins un élément correspond à tous les critères de requête spécifiés :

{ : { $elemMatch: { <query1>, <query2>, ... } } }

Bien que nous puissions utiliser des opérateurs de comparaison tels que $lte et $gte, si nous ne spécifions qu’une seule condition de requête dans $elemMatch, et que nous n’utilisons pas les opérateurs $not ou $ne, l’utilisation de $elemMatch peut être omise car il remplirait essentiellement la même fonction.

Il y a quelques autres choses à garder à l’esprit lors de l’utilisation de cet opérateur, principalement :

  • Vous ne pouvez pas spécifier une expression $where dans une opération $elemMatch.
  • Vous ne pouvez pas spécifier une expression de requête $text dans une opération $elemMatch.

Par exemple, nous avons les documents suivants dans la collection de résultats des étudiants :

{ _id: 1, results: [ 92, 89, 98 ] }
{ _id: 2, results: [ 85, 99, 99 ] }

La requête suivante correspond uniquement aux documents dont le tableau de résultats contient au moins un élément qui est à la fois supérieur ou égal à 90 et inférieur à 95 :

db.studentresults.find(  { results: { $elemMatch: { $gte: 90, $lt: 95 } } })

Notre requête renvoie le document suivant, puisque l’élément 92 est à la fois supérieur ou égal à 90 et inférieur à 95 :

{ "_id" : 1, "results" :[ 92, 89, 98 ] }

$size

L’opérateur $size renvoie les documents dont la taille du tableau correspond au nombre d’éléments spécifié dans l’argument :

{ field: { $size: value } }

Voici un exemple :

db.collection.find( { field: { $size: 2 } });

Cela renverrait tous les documents de la collection spécifiée dont le champ est un tableau comportant 2 éléments : { field: [ orange, apple] } and { field: [ blue, red] }, but not { field: blue} or { field: [ raspberry, lemon, grapefruit ] }.

Cependant, alors que nous pouvons saisir une valeur spécifique comme taille, nous ne pouvons pas spécifier des plages de valeurs comme taille.

Opérateurs géospatiaux

MongoDB vous permet de stocker des données géospatiales sous la forme de types GeoJSON. GeoJSON est un format standard ouvert basé sur la notation objet JavaScript qui peut représenter des caractéristiques géographiques et prendre en charge des attributs non spatiaux. Il existe deux types d’opérateurs géospatiaux dont nous allons parler dans cet article : les spécificateurs de géométrie et les sélecteurs de requête.

$geometry

Cet opérateur mentionne la géométrie GeoJSON à utiliser avec les opérateurs de requête géospatiale suivants : $geoIntersects, $geoWithin,$nearSphere, and $near. $geometry utilise EPSG:4326 comme système de référence de coordonnées (CRS) par défaut.

Pour mentionner des objets GeoJSON avec le CRS par défaut, vous pouvez utiliser le code suivant pour $geometry:

$geometry: {
   type: "<GeoJSON object type>",
   coordinates: [ <coordinates> ]
}

Pour mentionner un polygone GeoJSON à anneau unique avec un CRS MongoDB adapté, vous pouvez utiliser le code suivant (vous ne pouvez l’utiliser que pour $geoWithin and $geoIntersects) :

$geometry: {
   type: "Polygon",
   coordinates: [ <coordinates> ],
   crs: {
      type: "name",
      properties: { name: "urn:x-mongodb:crs:strictwinding:EPSG:4326" }
   }
}

$polygon

L’opérateur $polygon peut être utilisé pour spécifier un polygone pour une requête géospatiale $geoWithin sur des paires de coordonnées anciennes. Cette requête renverra alors les paires qui se situent dans les limites du polygone. Toutefois, $polygon n’effectuera pas de requête sur les objets GeoJSON. Pour définir un polygone, vous devez spécifier un tableau de points de coordonnées comme suit :

{
   : {
      $geoWithin: {
         $polygon: [ [ <x1> , <y1> ], [ <x2> , <y2> ], [ <x3> , <y3> ], ... ]
      }
   }
}

Ici, le dernier point est implicitement relié au premier. Vous pouvez mentionner autant de points ou de côtés que vous le souhaitez.

Par exemple, la requête suivante renvoie tous les documents dont les coordonnées se trouvent dans le polygone défini par [0,0], [1,5] et [3,3] :

db.places.find(
  {
     loc: {
       $geoWithin: { $polygon: [ [ 0 , 0 ], [ 1 , 5 ], [ 3 , 3 ] ] }
     }
  }
)

$geoWithin

Cet opérateur peut être utilisé pour choisir les documents contenant des données géospatiales qui sont entièrement contenus dans une forme spécifique. La forme spécifiée peut être soit un multipolygone GeoJSON, soit un polygone GeoJSON (à plusieurs anneaux ou à un seul anneau), soit une forme qui peut être définie par des paires de coordonnées anciennes.

L’opérateur $geoWithin s’appuiera sur l’opérateur $geometry pour mentionner l’objet GeoJSON.

Pour mentionner les multi-polygones ou polygones GeoJSON via le système de référence des coordonnées (CRS) par défaut, vous pouvez utiliser la syntaxe mentionnée ci-dessous :

{
   : {
      $geoWithin: {
         $geometry: {
            type: <"Polygon" or "MultiPolygon"> ,
            coordinates: [ <coordinates> ]
         }
      }
   }
}

Pour les requêtes $geoWithin qui mentionnent les géométries GeoJSON dont la surface est supérieure à un seul hémisphère, l’utilisation du CRS par défaut entraînerait des requêtes pour les géométries complémentaires.

Pour mentionner un polygone GeoJSON à un seul hémisphère avec un SRC MongoDB personnalisé, vous pouvez exploiter le prototype mentionné ci-dessous dans l’expression $geometry:

{
   : {
      $geoWithin: {
         $geometry: {
           type: "Polygon" ,
           coordinates: [ <coordinates> ],
           crs: {
              type: "name",
              properties: { name: "urn:x-mongodb:crs:strictwinding:EPSG:4326" }
           }
         }
      }
   }
}

L’exemple suivant sélectionne toutes les données localisées qui existent entièrement dans un polygone GeoJSON, la superficie du polygone étant inférieure à celle d’un seul hémisphère :

db.places.find(
   {
     loc: {
       $geoWithin: {
          $geometry: {
             type : "Polygon" ,
             coordinates: [ [ [ 0, 0 ], [ 3, 6 ], [ 6, 1 ], [ 0, 0 ] ] ]
          }
       }
     }
   }
)

$box

Vous pouvez utiliser $box pour spécifier un rectangle pour une requête géospatiale $geoWithin afin de fournir les documents qui se trouvent dans les limites du rectangle, en fonction de leurs données de localisation ponctuelles. Lorsque vous utilisez $geoWithin avec $box, vous obtenez des documents basés sur les coordonnées de la requête. Dans ce scénario, $geoWithin n’effectuera pas de requête pour les formes GeoJSON.

Pour tirer parti de l’opérateur $box, vous devez mentionner les coins supérieurs droit et inférieurs gauche du rectangle dans un objet de type tableau :

{ <location field> : { $geoWithin: { $box: [ [ <bottom left coordinates> ],
 [ <upper right coordinates> ] ] } } }

La requête susmentionnée calculera la distance en utilisant la géométrie planaire (plate). La requête suivante renverra tous les documents qui sont à l’intérieur de la boîte ayant des points à : [0,0], [0,30], [30,0], [30,30] :

db.places.find ( { 
 loc: { $geoWithin: { $box: [ [ 0,0 ], [ 30,30 ] ] } }
} )

$nearSphere

Vous pouvez utiliser $nearSphere pour mentionner un point pour lequel une requête géospatiale renvoie les documents du plus proche au plus éloigné.

MongoDB utilise la géométrie sphérique pour calculer les distances pour $nearSphere. Il aura besoin d’un index géospatial comme suit :

  1. index 2d pour les données de localisation décrites comme des paires de coordonnées anciennes. Pour exploiter un index 2d sur des points GeoJSON, vous devez générer l’index sur le champ de coordonnées de l’objet GeoJSON.
  2. index 2dsphere pour les données de localisation décrites comme des points GeoJSON.

Pour mentionner un point GeoJSON, vous pouvez exploiter la syntaxe suivante :

{
  $nearSphere: {
     $geometry: {
        type : "Point",
        coordinates : [ <longitude>, <latitude> ]
     },
     $minDistance: <distance in meters>,
     $maxDistance: <distance in meters> 
  }
}

Ici, $minDistance et $maxDistance sont facultatifs. $minDistance peut limiter les résultats aux documents qui sont au moins à la distance spécifiée du centre. Vous pouvez utiliser $maxDistance pour l’un ou l’autre des index.

Maintenant, considérez une collection de « places » qui se compose de documents dont le champ d’emplacement a un indice 2dsphere. L’exemple suivant renverrait les points dont l’emplacement est situé à au moins 2 000 mètres et au plus 6 000 mètres du point que vous avez choisi, classés du plus proche au plus éloigné :

db.places.find(
   {
     location: {
        $nearSphere: {
           $geometry: {
              type : "Point",
              coordinates : [ -43.9532, 50.32 ]
           },
           $minDistance: 2000,
           $maxDistance: 6000
        }
     }
   }
)

$geoIntersects

L’opérateur $geoIntersects vous permet de sélectionner les documents dont les données géospatiales intersectent avec un objet GeoJSON particulier (c’est-à-dire où la convergence de l’objet spécifié et des données est non vide). Il s’appuie sur l’opérateur $geometry pour spécifier l’objet GeoJSON.

Pour mentionner des multi-polygones ou des polygones GeoJSON par le biais du système de référence de coordonnées (Coordinate Reference System ou CRS) par défaut, vous pouvez utiliser la syntaxe suivante :

{ <location field>: {
     $geoIntersects: {
        $geometry: {
           type: "<GeoJSON object type>" ,
           coordinates: [ <coordinates> ]
        }
     }
  }
}

L’instance suivante utilisera $geoIntersects pour prélever toutes les données localisées qui intersectent le polygone décrit par le tableau de coordonnées :

db.places.find(
   {
     loc: {
       $geoIntersects: {
          $geometry: {
             type: "Polygon" ,
             coordinates: [
               [ [ 0, 0 ], [ 2, 6 ], [ 4, 1 ], [ 0, 0 ] ]
             ]
          }
       }
     }
   }
)

$center

L’opérateur $center mentionne un cercle pour une requête $geoWithin qui renvoie les paires de coordonnées héritées qui se trouvent dans les limites du cercle.

$center ne renvoie pas d’objets GeoJSON. Pour exploiter l’opérateur $center, vous devez spécifier un tableau qui contient :

  1. Le rayon du cercle, tel que mesuré dans les unités utilisées par le système de coordonnées.
  2. Les coordonnées de grille du point central du cercle.
{
  <location field> : {
      $geoWithin: { $center: [ [ <x> , <y> ] , <radius> ] }
   }
}

L’exemple mentionné ci-dessous renverra tous les documents dont les coordonnées peuvent être trouvées dans le cercle centré sur [2,3] et dont le rayon est de 40 :

db.places.find(
   { loc: { $geoWithin: { $center: [ [2, 3], 40 ] } } }
)

Opérateurs de projection

Vous pouvez utiliser des opérateurs de projection pour mentionner les champs retournés par une opération. Les opérateurs de projection MongoDB permettent d’utiliser la fonction find() avec des arguments de filtrage des données. Cela aide les utilisateurs à extraire uniquement les champs de données requis d’un document. Ainsi, il permet de projeter des données transparentes et concises sans affecter les performances globales de la base de données.

$elemMatch (projection)

L’opérateur $elemMatch est chargé de limiter le contenu d’un champ des résultats de la requête pour ne contenir que le premier élément correspondant à la condition $elemMatch.

Voici quelques éléments que vous devez garder à l’esprit avant d’utiliser $elemMatch:

  • À partir de MongoDB 4.4, indépendamment de l’ordre des champs dans le document, la projection $elemMatch d’un champ existant renvoie le champ après l’inclusion d’autres champs existants.
  • Les opérateurs $elemMatch et $ projettent tous deux le premier élément correspondant d’un tableau en fonction d’une condition spécifiée. L’opérateur $ projetterait le premier élément correspondant d’un tableau à partir de chaque document d’une collection en fonction d’une condition de l’énoncé de la requête, tandis que l’opérateur de projection $elemMatch prend un argument de condition explicite. Cela vous permet de projeter sur la base d’une condition qui n’est pas présente dans la requête, ou si vous devez projeter sur la base de divers champs dans les documents intégrés au tableau.

Vous devez également être conscient des restrictions suivantes avant d’utiliser l’opérateur $elemMatch sur vos données :

  • Vous ne pouvez pas mentionner une expression de requête $text au sein d’un opérateur $elemMatch.
  • db.collection.find() les opérations sur les vues ne prennent pas en charge l’opérateur de projection $elemMatch.

L’exemple suivant sur l’opérateur de projection $elemMatch suppose une collection schools avec les documents suivants :

{
 _id: 1,
 zipcode: "63108",
 students: [
              { name: "mark", school: 102, age: 9 },
              { name: "geoff", school: 101, age: 13 },
              { name: "frank", school: 104, age: 12 }
           ]
}
{
 _id: 2,
 zipcode: "63110",
 students: [
              { name: "harry", school: 103, age: 14 },
              { name: "george", school: 103, age: 7 },
           ]
}
{
 _id: 3,
 zipcode: "63108",
 students: [
              { name: "harry", school: 103, age: 14 },
              { name: "george", school: 103, age: 7 },
           ]
}
{
 _id: 4,
 zipcode: "63110",
 students: [
              { name: "jim", school: 103, age: 9 },
              { name: "michael", school: 103, age: 12 },
           ]
}

Dans ce cas, l’opération find() recherche tous les documents où la valeur du champ code postal est 63110. La projection $elemMatch renverrait uniquement le premier élément correspondant du tableau students où le champ school a une valeur de 103 :

db.schools.find( { zipcode: "63110" },
                 { students: { $elemMatch: { school: 103 } } } )

Voici à quoi ressemblera le résultat :

{ "_id" : 2, "students" : [ { "name" : "harry", "school" : 103, "age" : 14 } ] }
{ "_id" : 4, "students" : [ { "name" : "jim", "school" : 103, "age" : 9 } ] }

$slice (projection)

L’opérateur de projection $slice peut être utilisé pour spécifier le nombre d’éléments d’un tableau à retourner dans le résultat de la requête :

db.collection.find(
   <query> ,
   { <arrayField> : { $slice: <number> } }
);

Il peut également être exprimé de la manière suivante :

db.collection.find(
  <query> ,
   { <arrayField> : { $slice: [ <number> , <number> ] } }
);

Pour le démontrer, vous pouvez créer un exemple de collection de tweets avec les documents suivants :

db.posts.insertMany([
   {
     _id: 1,
     title: "Nuts are not blueberries.",
     comments: [ { comment: "0. true" }, { comment: "1. blueberries aren't nuts."} ]
   },
   {
     _id: 2,
     title: "Coffee please.",
     comments: [ { comment: "0. Indubitably" }, { comment: "1. Cuppa tea please" }, { comment: "2. frappucino" }, { comment: "3. Mocha latte" }, { comment: "4. whatever" } ]
   }
])

L’opération suivante utiliserait l’opérateur de projection $slice sur le tableau de tweets pour retourner le tableau avec ses deux premiers éléments. Si un tableau contient moins de deux éléments, tous les éléments du tableau sont retournés :

db.posts.find( {}, { comments: { $slice: 2 } } )

Cette opération renverrait les documents suivants :

{
   "_id" : 1,
   "title" : "Nuts are not blueberries.",
   "comments" : [ { "comment" : "0. true" }, { "comment" : "1. blueberries aren't nuts." } ]
}
{
   "_id" : 2,
   "title" : "Coffee please.",
   "comments" : [ { "comment" : "0. Indubitably" }, { "comment" : "1. Cuppa tea please" } ]
}

$ (projection)

L’opérateur positionnel $ limite le contenu d’un tableau pour renvoyer le premier élément qui correspond à la condition d’interrogation de ce tableau. Vous pouvez utiliser $ dans le document de projection de la méthode find() ou de la méthode findOne() lorsque vous n’avez besoin que d’un élément particulier du tableau dans les documents choisis.

Voici à quoi ressemble la syntaxe de l’opérateur $:

db.collection.find( { <array>: <condition> ... },
                    { "<array>.$": 1 } )
db.collection.find( { <array.field>: <condition> ...},
                    { "<array>.$": 1 } )

Dans cet exemple, la collection students est composée des documents suivants :

{ "_id" : 1, "semester" : 2, "grades" : [ 75, 67, 93 ] }
{ "_id" : 2, "semester" : 2, "grades" : [ 60, 68, 72 ] }
{ "_id" : 3, "semester" : 2, "grades" : [ 95, 82, 67 ] }
{ "_id" : 4, "semester" : 3, "grades" : [ 89, 95, 70 ] }
{ "_id" : 5, "semester" : 3, "grades" : [ 68, 98, 82 ] }
{ "_id" : 6, "semester" : 3, "grades" : [ 65, 70, 76 ] }

Dans la requête suivante, la projection { "grades.$": 1 } renvoie uniquement le premier élément supérieur ou égal à 89 pour le champ grades:

db.students.find( { semester: 2, grades: { $gte: 89 } },
                  { "grades.$": 1 } )

Cette opération renvoie les documents suivants :

{"_id": 1, "grades": [93] }

Opérateurs d’évaluation

Vous pouvez exploiter les opérateurs d’évaluation de MongoDB pour jauger la structure globale des données ou un champ individuel dans un document.

Examinons quelques opérateurs d’évaluation MongoDB courants.

$mod

Vous pouvez utiliser cet opérateur pour faire correspondre des documents où la valeur d’un champ spécifié est égale au reste après avoir été divisé par une valeur spécifiée :

{ field: { $mod: [ divisor, remainder ] } }

Disons que vous avez un tableau de voitures appartenant à différentes marques que vous possédez dans votre salle d’exposition. La requête suivante vous donnerait toutes les marques de voitures dont le numéro de stock est un multiple de 250.

db.cars.find ( { qty: { $mod: [ 250,0 ] } } )

$jsonSchema

L’adresse $jsonSchema vous permet de faire correspondre les documents qui correspondent au schéma JSON spécifié. L’implémentation du schéma JSON par MongoDB comprend l’ajout du mot-clé bsonType, qui vous permet d’utiliser tous les types BSON au sein de l’opérateur $jsonSchema.

bsonType peut accepter les mêmes alias de chaîne que vous utiliseriez pour l’opérateur type. Voici à quoi ressemblerait la syntaxe de $jsonSchema:

{ $jsonSchema: <JSON Schema object> }

Ici, l’objet de schéma JSON est formaté sur la base du draft 4 de la norme de schéma JSON:

{ <keyword1>: <value1>, ... }

Voici un exemple pour démontrer le fonctionnement de $jsonSchema:

{ $jsonSchema: {
     required: [ "name", "major", "gpa", "address" ],
     properties: {
        name: {
           bsonType: "string",
           description: "must be a string and is required"
        },
        address: {
           bsonType: "object",
           required: [ "zipcode" ],
           properties: {
               "street": { bsonType: "string" },
               "zipcode": { bsonType: "string" }
           }
        }
     }
  }
}

Vous pouvez également utiliser $jsonSchema dans un validateur de document pour faire respecter le schéma spécifié lors des opérations de mise à jour et d’insertion :

db.createCollection(<collection> , { validator: { $jsonSchema: <schema> } } )
db.runCommand( { collMod: <collection>, validator:{ $jsonSchema: <schema> } } )

Gardez à l’esprit qu’il existe plusieurs choses qui ne sont pas prises en charge par l’opérateur $jsonSchema:

  1. Le type integer. Vous devez exploiter le type BSON long ou int avec le mot-clé bsonType.
  2. Les mots-clés inconnus.
  3. Les propriétés de liaison et l’hypermédia du schéma JSON, ainsi que l’utilisation des références JSON et des pointeurs JSON.

text

L’opérateur $text rechercherait un texte dans le contenu du champ spécifié, indexé avec un indice de texte :

{  
  $text:  
    {  
      $search: <string>,  
      $language: <string>,  
      $caseSensitive: <boolean>,  
      $diacriticSensitive: <boolean>   
    }  
}

Dans ce cas, le bout de code suivant passera au crible le tableau pour filtrer toutes les voitures contenant le texte « Porsche » :

db.cars.find( { $text: { $search: "Porsche" } } )

$regex

L’opérateur $regex offre des capacités d’expression régulière pour faire correspondre des chaînes de caractères dans les requêtes. MongoDB exploite les expressions régulières qui sont compatibles avec Perl :

{<field> : /pattern/ <options>}

L’exemple suivant permettrait de filtrer toutes les voitures dans lesquelles la chaîne « $78900 » est présente :

db.cars.find( { price: { $regex: /$78900/ } } )

$expr

L’opérateur $expr vous permet de tirer parti des expressions d’agrégation dans le langage de requête :

{ $expr: { <expression> } }

Vous pouvez également utiliser $expr pour construire des expressions de requête qui comparent les champs d’un même document dans une étape $match. Si l’étape $match se trouve être la partie d’une étape $lookup, $expr peut comparer des champs à l’aide de variables let.

$where

Vous pouvez exploiter l’opérateur $where pour transmettre une chaîne contenant une fonction JavaScript complète ou une expression JavaScript au système de requêtes. L’opérateur $where offre une plus grande flexibilité mais nécessite que la base de données traite la fonction ou l’expression JavaScript pour chaque document de la collection. Vous pouvez référencer ce document dans la fonction ou l’expression JavaScript en utilisant soit obj soit this.

Voici un exemple de la syntaxe :

{ $where: <string|JavaScript Code> }

Il y a quelques considérations clés à garder à l’esprit avant de nous plonger dans un exemple d’utilisation de l’opérateur $where:

  • Vous ne devez utiliser l’opérateur de requête $where que dans les documents de premier niveau. L’opérateur de requête $where ne fonctionnera pas dans un document imbriqué, comme dans une requête $elemMatch.
  • En général, vous ne devez utiliser $where que lorsque vous ne pouvez pas exprimer votre requête via un autre opérateur. Si vous devez utiliser $where, veillez à inclure au moins un autre opérateur de requête standard pour filtrer l’ensemble des résultats. L’utilisation indépendante de $where nécessite un balayage de la collection pour une exécution correcte.

Voici un exemple pour illustrer cela :

db.cars.find( { $where: function() {  
   return (hex_md5(this.name)== "9a43e617b50cd379dca1bc6e2a8")  
} } );

Opérateurs Bitwise

Les opérateurs bitwise renvoient des données basées sur des conditions de position de bit. En termes simples, ils sont utilisés pour faire correspondre des valeurs numériques ou binaires dans lesquelles n’importe quel bit d’un ensemble de positions binaires a une valeur de 1 ou 0.

$bitsAllSet

Cet opérateur correspondra à tous les documents où toutes les positions binaires fournies par la requête sont définies (c’est-à-dire 1) dans le champ :

{ <field> : { $bitsAllSet: <numeric bitmask> } }
{ <field> : { $bitsAllSet: < BinData bitmask> } }
{ <field> : { $bitsAllSet: [ <position1> , <position2> , ... ] } }

La valeur du champ doit être soit une instance BinData, soit numérique pour $bitsAllSet afin de correspondre au document actuel.

Dans l’instance suivante, nous exploitons une collection avec les documents suivants :

db.collection.save({ _id: 1, a: 54, binaryValueofA: "00110110" })
db.collection.save({ _id: 2, a: 20, binaryValueofA: "00010100" })
db.collection.save({ _id: 3, a: 20.0, binaryValueofA: "00010100" })
db.collection.save({ _id: 4, a: BinData(0, "Zg=="), binaryValueofA: "01100110" })

La requête mentionnée ci-dessous utilisera l’opérateur $bitsAllSet pour tester si le champ a a des bits placés en position 1 et en position 5, où le bit le moins significatif serait en position 0 :

db.collection.find( { a: { $bitsAllSet: [ 1, 5 ] } )

Cette requête correspondrait aux documents suivants :

{ "_id" : 1, "a" : 54, "binaryValueofA" : "00110110" }
{ "_id" : 4, "a" : BinData(0,"Zg=="), "binaryValueofA" : "01100110" }

$bitsAllClear

L’opérateur $bitsAllClear correspondra aux documents dans lesquels toutes les positions de bits fournies par la requête sont claires ou 0:

{ <field> : { $bitsAllClear: <numeric bitmask> } }
{ <field> : { $bitsAllClear: < BinData bitmask> } }
{ <field> : { $bitsAllClear: [ <position1> , <position2> , ... ] } }

Nous utiliserons ici l’exemple utilisé pour $bitsAllSet pour démontrer l’utilisation de $bitsAllClear. La requête suivante utiliserait cet opérateur pour vérifier si le champ a a les bits clairs aux positions 1 et 5 :

db.collection.find( { a: { $bitsAllClear: [ 1, 5 ] } } )

Cette requête correspondrait aux documents suivants :

{ "_id" : 2, "a" : 20, "binaryValueofA" : "00010100" }
{ "_id" : 3, "a" : 20, "binaryValueofA" : "00010100" }

Méta-opérateurs

Il existe divers modificateurs de requête qui vous permettent de modifier le comportement ou la sortie d’une requête dans MongoDB. Les interfaces du pilote peuvent fournir des méthodes de curseur qui les enveloppent pour votre usage.

$hint

MongoDB a déprécié $hint depuis la version 3.2. Mais, cet opérateur peut encore être disponible pour les pilotes MongoDB comme Go, Java, Scala, Ruby, Swift, etc. Il peut forcer l’optimiseur de requêtes à exploiter un index spécifique pour répondre à la requête, qui peut alors être mentionné soit par document, soit par nom d’index.

Vous pouvez également utiliser l’opérateur $hint pour tester les stratégies d’indexation et les performances des requêtes. Par exemple, prenez l’opération suivante :

db.users.find().hint( { age: 1 } )

Cette opération renverrait tous les documents de la collection appelée users en exploitant l’index sur le champ age.

Vous pouvez également mentionner un indice en utilisant l’une des formes suivantes :

db.users.find()._addSpecial( "$hint", { age : 1 } )
db.users.find( { $query: {}, $hint: { age : 1 } } )

Si un filtre d’index existe pour la forme de la requête, MongoDB ignorerait simplement le champ $hint.

$comment

L’opérateur $comment vous permet de joindre un commentaire à une requête dans n’importe quel contexte où $query peut apparaître. Comme les commentaires se propagent dans le journal du profil, l’ajout d’un commentaire peut faciliter l’interprétation et le traçage de votre profil.

Vous pouvez exploiter $comment de l’une des trois manières suivantes :

db.collection.find( { <query> } )._addSpecial( "$comment", <comment> )
db.collection.find( { <query> } ).comment( <comment> )
db.collection.find( { $query: { <query> }, $comment: <comment> } )

Si vous voulez joindre des commentaires à des expressions de requête dans d’autres contextes, comme avec db.collection.update(), utilisez l’opérateur de requête $comment au lieu du méta-opérateur.

$max

Vous pouvez mentionner une valeur $max pour spécifier la limite supérieure exclusive d’un index particulier afin de contraindre les résultats de find(). Cet opérateur spécifiera la limite supérieure pour toutes les clés d’un ordre spécifique dans l’index.

Mongosh vous donne la méthode max() suivante :

db.collection.find( { <query> } ).max( { field1: <max value> , ... fieldN: <max valueN> } )

Vous pouvez également mentionner $max avec les deux formes suivantes :

db.collection.find( { <query> } )._addSpecial( "$max", { field1: <max value1> ,
 ... fieldN: <max valueN> } )
db.collection.find( { $query: { <query> }, $max: { field1: <max value1> ,
 ... fieldN: <max valueN> } } )

Par exemple, si vous voulez spécifier la limite supérieure exclusive, gardez à l’esprit les opérations suivantes sur une collection nommée collection qui contient un index { age: 1 }:

db.collection.find( { <query> } ).max( { age: 100 } ).hint( { age: 1 } )

Cette opération limite la requête aux documents dont le champ âge est inférieur à 100 et force un plan de requête qui balayera l’index { age: 1 } de minKey à 100.

$explain

Cet opérateur vous donnera des informations sur le plan de requête. Il renvoie un document qui décrit les index et les processus utilisés pour renvoyer la requête. Cela peut être utile lorsque vous essayez d’optimiser une requête.

Vous pouvez mentionner l’opérateur $explain sous l’une des formes suivantes :

db.collection.find()._addSpecial( "$explain", 1 )
db.collection.find( { $query: {}, $explain: 1 } )

Meilleures pratiques pour les opérateurs MongoDB

Dans cette section, nous allons examiner certaines des meilleures pratiques lors de l’utilisation de ces opérateurs MongoDB.

Intégration et référencement

L’intégration est une extension naturelle de la modélisation des données. Elle vous permet d’éviter les jointures d’application, ce qui peut réduire les mises à jour et les requêtes.

Vous pouvez intégrer des données avec une relation 1:1 dans un seul document. Cela dit, les données avec une relation many:1 dans laquelle de « nombreux » objets apparaissent avec leurs documents parents peuvent également être de bons candidats.

Stocker ces types de données dans le même document semble être un choix prudent. Cependant, l’intégration offre de meilleures performances pour les opérations de lecture avec ce type de localité des données.

Les modèles de données intégrés peuvent également aider les développeurs à mettre à jour les données associées en une seule opération d’écriture. Cela fonctionne parce que les écritures de documents uniques sont transactionnelles.

Vous devriez envisager d’utiliser le référencement pour les scénarios suivants :

  • Lorsque vous mettez à jour un segment de document et qu’il continue à s’allonger, alors que le reste du document est statique.
  • Lorsqu’un document est consulté mais contient des données qui sont rarement utilisées. L’intégration ne ferait qu’augmenter les exigences en mémoire, le référencement est donc plus logique.
  • Lorsque la taille du document dépasse la limite de 16 Mo fixée par MongoDB. Cela peut se produire lors de la modélisation de relations many:1 (par exemple, employés:département).

Examiner le profilage et les modèles de requête

Pour la plupart des développeurs, la première étape pour optimiser les performances consiste à comprendre les modèles de requête réels et attendus. Une fois que vous connaissez suffisamment bien les modèles de requête de votre application, vous pouvez élaborer votre modèle de données et choisir les index appropriés.

Les développeurs MongoDB ont accès à divers outils puissants qui leur permettent d’améliorer les performances. Mais cela ne signifie pas que les profils et les modèles de requête peuvent être ignorés.

Par exemple, une façon simple d’améliorer les performances est d’analyser vos modèles de requête et de comprendre où vous pouvez intégrer les données. Voici d’autres moyens d’améliorer les performances de MongoDB après avoir identifié vos principaux modèles de requête :

  • S’assurer que vous disposez d’indices sur tous les champs sur lesquels vous effectuez des requêtes.
  • Stocker les résultats des sous-requêtes fréquentes sur les documents pour réduire la charge de lecture.
  • Examinez vos journaux pour repérer les requêtes lentes, puis vérifiez vos index.

Revoir l’indexation et la modélisation des données

En créant votre modèle de données, vous déciderez comment modéliser les relations entre les données. Choisir quand incorporer un document plutôt que de créer une référence à travers des documents séparés dans différentes collections, par exemple, est un exemple de considération spécifique à l’application.

Un avantage majeur des documents JSON est qu’ils permettent aux développeurs de modéliser les données en fonction des exigences de l’application. L’imbrication de sous-documents et de tableaux vous permet de modéliser des relations complexes entre les données en exploitant de simples documents texte.

Vous pouvez également utiliser MongoDB pour modéliser les éléments suivants :

  • Données géospatiales
  • Structures tabulaires, plates et en colonnes
  • Paires clé-valeur simples
  • Données de séries chronologiques
  • Arêtes et nœuds de structures de données de graphes connectés et similaires

Surveiller le sharding et la réplication

La réplication peut être essentielle pour améliorer les performances car elle augmente la disponibilité des données grâce à la mise à l’échelle horizontale. La réplication peut conduire à de meilleures performances et à plus de sécurité grâce à la redondance.

La surveillance des performances peut s’avérer fastidieuse et nécessiter des ressources et du temps supplémentaires pour assurer un bon fonctionnement. Vous pouvez tirer parti des outils de surveillance des performances disponibles sur le marché qui répondent à vos besoins spécifiques.

Par exemple, Kinsta APM peut saisir des informations horodatées sur les requêtes de la base de données MySQL de votre site WordPress, les processus PHP, les appels HTTP externes, et bien plus encore. Vous pouvez également utiliser cet outil gratuit pour déboguer :

  • Les longs appels d’API
  • Les longues requêtes URL externes
  • Des requêtes de base de données lentes, pour n’en citer que quelques-unes.

Dans MongoDB, la réplication peut être réalisée grâce à des ensembles de répliques qui permettent aux développeurs de copier les données d’un nœud ou d’un serveur primaire sur plusieurs secondaires. Cela permet à votre réplication d’exécuter certaines requêtes sur les secondaires plutôt que sur le primaire, évitant ainsi la contention et conduisant à un meilleur équilibrage de la charge.

Les clusters sharded de MongoDB sont un autre moyen d’améliorer potentiellement les performances. Tout comme la réplication, le sharding peut être utilisé pour distribuer de grands ensembles de données sur plusieurs serveurs.

En exploitant une clé de shard, les développeurs peuvent copier des shards ou des morceaux de données sur plusieurs serveurs. Ces serveurs peuvent travailler ensemble pour utiliser toutes les données.

Le sharding a son lot d’avantages, notamment la mise à l’échelle horizontale pour les écritures/lectures, une plus grande disponibilité et une capacité de stockage accrue.

Déterminer l’utilisation de la mémoire

MongoDB est plus performant lorsque l’ensemble de travail d’une application (c’est-à-dire les données et les index fréquemment utilisés) tient sans problème en mémoire. Bien que d’autres facteurs soient essentiels pour les performances, la taille de la RAM est la plus importante pour le dimensionnement de l’instance.

Lorsque l’ensemble de travail d’une application tient dans la RAM, l’activité de lecture sur le disque doit être faible. Mais si votre ensemble de travail dépasse la RAM du serveur ou de la taille de l’instance, l’activité de lecture commencera à augmenter.

Si vous constatez ce phénomène, vous pouvez peut-être résoudre le problème en passant à une instance plus grande qui dispose de plus de mémoire.

Placez les champs à valeurs multiples à la fin

Si vous indexez quelques champs et que l’un des champs que vous souhaitez interroger utilise l’un de ces opérateurs « multi-valeurs », vous devez les placer à la fin de l’index. Vous devez ordonner l’index de manière à ce que les champs interrogés pour des valeurs exactes apparaissent en premier et que les opérateurs « multi-valeurs » apparaissent en dernier dans l’index.

Une exception à cette règle serait le tri par rapport aux champs. Placez-les entre les champs « multi-valeurs » et les champs exacts pour réduire la quantité de tri en mémoire nécessaire.

Résumé

Pour MongoDB, la vitesse est primordiale. Pour renvoyer rapidement les requêtes, MongoDB utilise des opérateurs pour exécuter des tâches mathématiques ou logiques. En termes simples, comprendre les opérateurs MongoDB est la clé de la maîtrise de MongoDB.

Cet article a mis en évidence certains des principaux opérateurs MongoDB que vous pouvez utiliser sur vos données, tels que les opérateurs de comparaison, les opérateurs logiques, les méta-opérateurs et les opérateurs de projection, pour n’en citer que quelques-uns. Il vous aide également à comprendre comment vous pouvez utiliser les opérateurs MongoDB et les meilleures pratiques qui vous permettront d’en tirer le meilleur parti.

Parmi tous les opérateurs, lequel ou lesquels utilisez-vous le plus souvent, et pourquoi ? Partagez-les dans les commentaires ci-dessous – nous serions ravis de connaître votre avis !

Salman Ravoof

Salman Ravoof is a self-taught web developer, writer, creator, and a huge admirer of Free and Open Source Software (FOSS). Besides tech, he's excited by science, philosophy, photography, arts, cats, and food. Learn more about him on his website, and connect with Salman on Twitter.