MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Incluir campos específicos em um índice curinga no MongoDB


Ao criar um índice curinga no MongoDB, você tem a opção de especificar um único campo, todos os campos ou apenas alguns.

Você pode usar a wildcardProjection parâmetro para incluir ou excluir caminhos de campo específicos do índice curinga. Este artigo apresenta um exemplo de inclusão de campos específicos no índice curinga.

Exemplo de documento


Suponha que tenhamos uma coleção chamada pets com os seguintes 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")
	}
}

Poderíamos criar um índice curinga em toda a coleção, mas incluir apenas os campos que desejamos.

Criar o Índice


Aqui está um exemplo:
db.pets.createIndex(
  { "$**" : 1 },
  {
    "wildcardProjection" : {
      "details.type" : 1,
      "details.born" : 1
    }
  }
)

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

O { "$**" : 1 } parte é o que cria o índice curinga e o wildcardProjection parte é a parte que especifica quais campos incluir. Neste caso, incluímos o details.type campo e o details.born campo. Dando a eles um valor de 1 inclui-os explicitamente no índice.

Visualizar o Índice


Podemos visualizar os índices na coleção chamando o método getIndexes() método:
db.pets.getIndexes()

Resultado:
[
	{
		"v" : 2,
		"key" : {
			"_id" : 1
		},
		"name" : "_id_"
	},
	{
		"v" : 2,
		"key" : {
			"$**" : 1
		},
		"name" : "$**_1",
		"wildcardProjection" : {
			"details.type" : 1,
			"details.born" : 1
		}
	}
]

Podemos ver que existem dois índices.
  • O primeiro índice está no _id campo. Isso foi criado quando a coleção foi criada (o MongoDB cria um índice exclusivo no campo _id durante a criação de uma coleção).
  • O segundo índice é nosso índice curinga. Podemos ver que foi nomeado automaticamente $**_1 , e inclui os campos que especificamos.

Teste o índice


Também podemos executar algumas consultas para ver se nosso índice será usado ou não.

Em teoria, a seguinte consulta deve usar o índice:
db.pets.find( { "details.type" : "Dog" } )

Para testar isso, podemos anexar o explain() método para visualizar o plano 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 ele usou uma varredura de índice (IXSCAN) em nosso índice.

Em contraste com isso, veja o que acontece quando executamos uma consulta em um campo que não incluído no índice:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()

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

Neste caso ele fez uma varredura de coleção (COLLSCAN), então como esperado, não utilizou o índice.