sql >> Base de Datos >  >> NoSQL >> MongoDB

Excluir campos específicos en el índice de comodines en MongoDB

Cuando crea un índice comodín en MongoDB, tiene la opción de especificar un solo campo, todos los campos o solo algunos.

También tiene la opción de excluir ciertos campos. En otras palabras, puede especificar todos los campos excepto para uno o más campos específicos.

Puedes usar la wildcardProjection parámetro para incluir o excluir rutas de campo específicas del índice comodín. Este artículo presenta un ejemplo de exclusión de campos específicos en el índice de comodines.

Documento de ejemplo

Supongamos que tenemos una colección llamada pets con los siguientes documentos:

{
	"_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")
	}
}

Podríamos crear un índice comodín en toda la colección, excluyendo ciertos campos.

Crear el índice

He aquí un ejemplo:

db.pets.createIndex(
  { "$**" : 1 },
  {
    "wildcardProjection" : {
      "details.awards" : 0,
      "details.eats" : 0
    }
  }
)

Salida:

{
	"createdCollectionAutomatically" : false,
	"numIndexesBefore" : 1,
	"numIndexesAfter" : 2,
	"ok" : 1
}

El { "$**" : 1 } parte es lo que crea el índice comodín y la wildcardProjection part es la parte que especifica qué campos excluir. En este caso, hemos excluido los details.awards y el campo details.eats campo. Dándoles un valor de 0 los excluye explícitamente del índice.

Ver el índice

Podemos ver los índices de la colección llamando a getIndexes() método:

db.pets.getIndexes()

Resultado:

[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"$**" : 1
		},
		"name" : "$**_1",
		"wildcardProjection" : {
			"details.awards" : 0,
			"details.eats" : 0
		}
	}
]

Podemos ver que hay dos índices.

  • El primer índice está en _id campo. Esto se creó cuando se creó la colección (MongoDB crea un índice único en el campo _id durante la creación de una colección).
  • El segundo índice es nuestro índice comodín. Podemos ver que se ha nombrado automáticamente $**_1 , e incluye los campos que especificamos junto con un valor de 0 , lo que significa que están explícitamente excluidos del índice.

Prueba el índice

También podemos ejecutar algunas consultas para ver si se usará nuestro índice y si los campos excluidos realmente se excluirán

La siguiente consulta debe usar el índice:

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

Debería usar el índice porque no excluimos el details.type campo del índice.

Para probar esto, podemos agregar explain() método para ver el plan de consulta:

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

Resultado:

{
	"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
}

Podemos ver que usó un escaneo de índice (IXSCAN) en nuestro índice.

En contraste con esto, esto es lo que sucede cuando ejecutamos una consulta en uno de los campos que excluimos del índice:

db.pets.find( { "details.awards.Florida Dog Awards" : "Top Dog" } ).explain()

Resultado:

{
	"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
}

En este caso, realizó un análisis de la colección (COLLSCAN), por lo que, como era de esperar, no utilizó el índice.