MongoDB prend parfaitement en charge les tableaux et offre une grande flexibilité dans votre mode de document. Par exemple, vous pouvez incorporer des tableaux dans des documents et également incorporer des documents dans des tableaux, etc. Cependant, travailler avec des tableaux comporte un certain nombre de pièges dans MongoDB. Dans cet article, nous examinerons certains des problèmes rencontrés par MongoDB avec les index et les tableaux.
Index multi-clés
Dans MongoDB, vous pouvez indexer un champ de tableau pour créer une entrée d'index pour chaque élément du tableau. L'index résultant est appelé un index « multi-clé ». Des index multi-clés peuvent être créés sur des valeurs scalaires ou des documents intégrés. Pour plus d'informations sur les index multiclés, consultez cette documentation.
Les index multi-clés, bien qu'utiles, ont plusieurs limites :
- Si vous créez un index multiclé composé, vous avez au plus un champ qui est un tableau.
- Un index composé ne peut pas être une clé de partition.
- Un index composé ne peut pas être un index haché.
L'un des aspects les plus intéressants des index multi-clés est la façon dont les limites d'intersection d'index sont calculées.
Limites d'intersection d'index
Voici comment la documentation MongoDB définit les limites d'intersection d'index :
"Les limites d'un parcours d'index définissent les parties d'un index à rechercher lors d'une requête. Lorsqu'il existe plusieurs prédicats sur un index, MongoDB tentera de combiner les limites de ces prédicats par intersection ou composition afin de produire un scan avec des bornes plus petites.”
Requêtes de plage sur les tableaux
Commençons par un exemple simple pour voir comment MongoDB calcule les limites d'index pour les requêtes sur les tableaux. Supposons que nous ayons les trois documents suivants dans une collection :
{x :65}{x :35}{x :[12,95]}
Nous émettons la requête suivante :
db.coll.find({x :{ $gt :22, $lt:55})
La requête est assez simple. Vous vous attendriez à ce que la réponse soit {x:35} mais la requête renvoie :
{x:35}{x:[25,95]}
La raison vient de la façon dont MongoDB gère les tableaux. Le même élément du tableau n'a pas besoin de correspondre aux deux conditions ; tant qu'il y a un élément correspondant à chaque condition, c'est une correspondance. Donc, dans ce cas, les bornes sont [22, Infinity] et [-Infinity, 55]. Puisqu'un opérateur 'elemMatch' n'est pas utilisé, MongoDB n'utilise pas l'intersection d'index. MongoDB ne précise pas laquelle de ces plages [22, Infinity] ou [-Infinity, 55] sera utilisée pour l'exécution de la requête.
Si nous voulons utiliser l'intersection d'index, nous devons utiliser la requête suivante :
db.coll.find(x :{ $elemMatch :{$gt :22,$lt:55}})
Lorsque vous l'utilisez, MongoDB croise les limites de l'index et utilise [22, 55] comme limites. Comme prévu, cette requête ne renvoie aucun résultat (elemMatch ne correspond pas aux non-tableaux). Donc, essentiellement, les requêtes de plage sur les tableaux sont assez inutiles sans l'opérateur $elemMatch.
Index multi-clés composés – Mélange de champs de tableau et non-tableau
Envisagez une collection avec les documents suivants :
{article :35, prix :[250,35]}......{article :106, prix :[1500,65]}
Nous allons ajouter un index composé sur cette collection :
db.ensureIndex({item:1,prices:1});
Exécutons maintenant une requête simple :
db. coll. trouver({item :{$gt:12, $lt:65}});
La requête semble assez simple, car nous utilisons un élément non-tableau avec une plage fixe. Je m'attends à ce que les limites d'intersection de l'index soient quelque chose comme item :[[12,65] ] pour la requête, cependant, si vous exécutez une explication, vous verrez ceci :
"indexBounds" :{"item" :[ [ -Infinity, 65 ] ],"prices" :[ [ { "$minElement" :1 }, { "$maxElement" :1 } ] ]},La raison en est que MongoDB détecte qu'il s'agit d'un index multiclé et ne traite pas l'intersection des limites de l'index, indépendamment du fait que votre requête n'utilise aucun champ de tableau. La morale de l'histoire est que lorsque vous mélangez des champs tableau et non tableau dans un index, gardez toujours un œil sur les limites d'intersection de votre index. Il y a de fortes chances que ce ne soit pas efficace.