MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

Exclure des champs spécifiques dans l'index générique dans MongoDB

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 de 0 , 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.