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

Criar um índice curinga no MongoDB


Existem várias maneiras de criar um índice no MongoDB e, a partir do MongoDB 4.2, podemos criar índices curinga.

Um índice curinga pode ser considerado um tipo de filtro que corresponde automaticamente a qualquer campo, subdocumento ou array em uma coleção e, em seguida, indexa essas correspondências.

Isso pode ser útil se seus documentos contiverem dados não estruturados com campos diferentes em hierarquias diferentes. Nesses casos, não há como prever qual deve ser o índice, porque você não sabe quais dados estarão em cada documento.

Índices curinga podem ser úteis com esses dados não estruturados, porque indexam todos os valores escalares do campo, automaticamente recursivamente em quaisquer subdocumentos ou matrizes e indexando todos os campos escalares no subdocumento/matriz.

Coleção de exemplo


Os índices curinga não são para todas as coleções. Você só criaria um índice curinga em determinadas coleções com documentos que contêm dados não estruturados com campos diferentes em hierarquias diferentes.

Abaixo está um exemplo de uma coleção chamada pets que pode ser um bom candidato para um índice curinga:
{
	"_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")
	}
}

Cada um dos 3 documentos nesta coleção tem um details campo, mas eles contêm campos diferentes dentro desse campo. Não é consistente. Isso normalmente dificultaria a criação de um índice, porque não sabemos quais campos estarão em cada documento. Provavelmente precisaríamos criar vários índices, após uma análise cuidadosa das possíveis estruturas de documentos.

Felizmente, podemos criar um índice curinga.

Mas primeiro, vamos dar uma olhada na aparência de um plano de consulta ao consultar um desses campos. Imagine que queremos descobrir qual cachorro recebeu o prêmio de “Cão Mais Rápido” na Maratona de Nova York. Poderíamos fazer o seguinte:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } )

E se quiséssemos verificar o plano de consulta, poderíamos anexar explain() até o fim:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()

Que retorna o seguinte:
{
	"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
}

O que nos diz que ia fazer uma varredura de coleção (COLLSCAN), o que significa que ele precisa varrer todos os documentos procurando o campo.

Criar um índice curinga


Aqui está um exemplo de criação de um índice curinga para a coleção acima.
db.pets.createIndex({ "details.$**": 1 });

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

É isso. O índice curinga foi criado.

Para criar o índice curinga, usamos o nome do campo no qual queríamos criar o índice (neste caso, os details campo), então anexamos isso com um ponto (. ), e então a parte importante, o $** papel.

O $** especifica que um índice curinga deve ser criado a partir desse campo e de todos os seus subdocumentos.

Prefixando o $** com details limita o escopo do índice curinga apenas aos details campo.

Agora vamos verificar novamente o plano de consulta para a consulta mencionada:
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" : "7DFA23ED",
		"winningPlan" : {
			"stage" : "FETCH",
			"inputStage" : {
				"stage" : "IXSCAN",
				"keyPattern" : {
					"$_path" : 1,
					"details.awards.New York Marathon" : 1
				},
				"indexName" : "details.$**_1",
				"isMultiKey" : false,
				"multiKeyPaths" : {
					"$_path" : [ ],
					"details.awards.New York Marathon" : [ ]
				},
				"isUnique" : false,
				"isSparse" : false,
				"isPartial" : false,
				"indexVersion" : 2,
				"direction" : "forward",
				"indexBounds" : {
					"$_path" : [
						"[\"details.awards.New York Marathon\", \"details.awards.New York Marathon\"]"
					],
					"details.awards.New York Marathon" : [
						"[\"Fastest Dog\", \"Fastest Dog\"]"
					]
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"ok" : 1
}

Desta vez, a varredura de coleção (COLLSCAN) foi substituída por uma varredura de índice (IXSCAN) em nosso índice curinga recém-criado.

Cada campo em nossos details campo foi indexado como um caminho/valor e há uma entrada no índice para cada campo na hierarquia. Onde o valor do campo é um subdocumento (como nosso. awards campo), a indexação desceu para o subdocumento e repetiu o processo.

Criando um índice curinga em todos os caminhos de campo


No exemplo anterior, criamos um índice curinga em um único caminho de campo. É possível criar um índice curinga em todos os caminhos de campos simplesmente usando o $** sem prefixá-lo com um campo.

Por exemplo, poderíamos ter feito isso:
db.pets.createIndex({ "$**": 1 });

Isso teria criado um índice curinga em todos os caminhos de campo.

Na verdade, isso não é bem verdade. Por padrão, os índices curinga não são criados no _id campo. Para incluir o _id campo, você precisaria incluí-lo em um wildcardProjection documento.

Não é possível criar índices curinga? Verifique esta configuração.


O mongod featureCompatibilityVersion deve ser pelo menos 4.2 para criar índices curinga.

Você pode verificar essa configuração com o seguinte código:
db.adminCommand( 
    { 
        getParameter: 1, 
        featureCompatibilityVersion: 1 
    } 
)

Você pode configurá-lo usando o setFeatureCompatibilityVersion comando:
db.adminCommand( { setFeatureCompatibilityVersion: "4.4" } )

A setFeatureCompatibilityVersion comando precisa ser executado no admin base de dados.