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

Inclure des champs spécifiques dans un 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 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'inclusion 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, mais n'inclure que les champs souhaités.

Créer l'index

Voici un exemple :

db.pets.createIndex(
  { "$**" : 1 },
  {
    "wildcardProjection" : {
      "details.type" : 1,
      "details.born" : 1
    }
  }
)

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 à inclure. Dans ce cas, nous avons inclus le details.type champ et le details.born domaine. En leur donnant une valeur de 1 les inclut explicitement dans l'index.

Afficher l'index

Nous pouvons afficher 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.type" : 1,
			"details.born" : 1
		}
	}
]

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.

Tester l'index

Nous pouvons également exécuter des requêtes pour voir si notre index sera utilisé ou non.

En théorie, la requête suivante devrait utiliser l'index :

db.pets.find( { "details.type" : "Dog" } )

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 un champ qui n'est pas inclus dans l'index :

db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()

Résultat :

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "PetHotel.pets",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"details.awards.New York Marathon" : {
				"$eq" : "Fastest Dog"
			}
		},
		"queryHash" : "EC0D5185",
		"planCacheKey" : "EC0D5185",
		"winningPlan" : {
			"stage" : "COLLSCAN",
			"filter" : {
				"details.awards.New York Marathon" : {
					"$eq" : "Fastest 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.