Lorsque vous créez un index générique dans MongoDB, vous avez la possibilité de spécifier un seul champ, tous les champs ou seulement certains.
Vous avez également la possibilité d'exclure certains champs. En d'autres termes, vous pouvez spécifier tous les champs sauf pour un ou plusieurs champs spécifiques.
Vous pouvez utiliser le wildcardProjection
paramètre pour inclure ou exclure des chemins de champ spécifiques de l'index générique. Cet article présente un exemple d'exclusion de champs spécifiques dans l'index générique.
Exemple de document
Supposons que nous ayons une collection appelée pets
avec les documents suivants :
{ "_id" : 1, "name" : "Wag", "details" : { "type" : "Dog", "weight" : 20, "awards" : { "Florida Dog Awards" : "Top Dog", "New York Marathon" : "Fastest Dog", "Sumo 2020" : "Biggest Dog" } } } { "_id" : 2, "name" : "Fetch", "details" : { "born" : ISODate("2020-06-22T14:00:00Z"), "color" : "Black" } } { "_id" : 3, "name" : "Scratch", "details" : { "eats" : [ "Mouse Porridge", "Bird Soup", "Caviar" ], "type" : "Cat", "born" : ISODate("2020-12-19T14:00:00Z") } }
Nous pourrions créer un index générique sur l'ensemble de la collection, tout en excluant certains champs.
Créer l'index
Voici un exemple :
db.pets.createIndex(
{ "$**" : 1 },
{
"wildcardProjection" : {
"details.awards" : 0,
"details.eats" : 0
}
}
)
Sortie :
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
Le { "$**" : 1 }
part est ce qui crée l'index générique, et le wildcardProjection
part est la partie qui spécifie les champs à exclure. Dans ce cas, nous avons exclu les details.awards
champ et le details.eats
domaine. En leur donnant une valeur de 0
les exclut explicitement de l'index.
Afficher l'index
Nous pouvons voir les index sur la collection en appelant le getIndexes()
méthode :
db.pets.getIndexes()
Résultat :
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" }, { "v" : 2, "key" : { "$**" : 1 }, "name" : "$**_1", "wildcardProjection" : { "details.awards" : 0, "details.eats" : 0 } } ]
On voit qu'il y a deux index.
- Le premier index est sur le
_id
domaine. Celui-ci a été créé lors de la création de la collection (MongoDB crée un index unique sur le champ _id lors de la création d'une collection). - Le deuxième index est notre index générique. Nous pouvons voir qu'il a été nommé automatiquement
$**_1
, et il inclut les champs que nous avons spécifiés avec une valeur de0
, ce qui signifie qu'ils sont explicitement exclus de l'index.
Tester l'index
Nous pouvons également exécuter des requêtes pour voir si notre index sera utilisé et si les champs exclus seront vraiment exclus
La requête suivante doit utiliser l'index :
db.pets.find( { "details.type" : "Dog" } )
Il devrait utiliser l'index car nous n'avons pas exclu le details.type
champ de l'index.
Pour tester cela, nous pouvons ajouter le explain()
méthode pour afficher le plan de requête :
db.pets.find( { "details.type" : "Dog" } ).explain()
Résultat :
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "PetHotel.pets", "indexFilterSet" : false, "parsedQuery" : { "details.type" : { "$eq" : "Dog" } }, "queryHash" : "F1C5286F", "planCacheKey" : "5326DE93", "winningPlan" : { "stage" : "FETCH", "inputStage" : { "stage" : "IXSCAN", "keyPattern" : { "$_path" : 1, "details.type" : 1 }, "indexName" : "$**_1", "isMultiKey" : false, "multiKeyPaths" : { "$_path" : [ ], "details.type" : [ ] }, "isUnique" : false, "isSparse" : false, "isPartial" : false, "indexVersion" : 2, "direction" : "forward", "indexBounds" : { "$_path" : [ "[\"details.type\", \"details.type\"]" ], "details.type" : [ "[\"Dog\", \"Dog\"]" ] } } }, "rejectedPlans" : [ ] }, "ok" : 1 }
Nous pouvons voir qu'il a utilisé une analyse d'index (IXSCAN) sur notre index.
En revanche, voici ce qui se passe lorsque nous exécutons une requête sur l'un des champs que nous avons exclus de l'index :
db.pets.find( { "details.awards.Florida Dog Awards" : "Top Dog" } ).explain()
Résultat :
{ "queryPlanner" : { "plannerVersion" : 1, "namespace" : "PetHotel.pets", "indexFilterSet" : false, "parsedQuery" : { "details.awards.Florida Dog Awards" : { "$eq" : "Top Dog" } }, "queryHash" : "16FBC17B", "planCacheKey" : "16FBC17B", "winningPlan" : { "stage" : "COLLSCAN", "filter" : { "details.awards.Florida Dog Awards" : { "$eq" : "Top Dog" } }, "direction" : "forward" }, "rejectedPlans" : [ ] }, "ok" : 1 }
Dans ce cas, il a fait une analyse de collection (COLLSCAN), donc comme prévu, il n'a pas utilisé l'index.