MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Crea un indice con caratteri jolly in MongoDB

Esistono diversi modi per creare un indice in MongoDB e da MongoDB 4.2 possiamo creare indici con caratteri jolly.

Un indice con caratteri jolly può essere pensato come una sorta di filtro che corrisponde automaticamente a qualsiasi campo, documento secondario o matrice in una raccolta e quindi indicizza tali corrispondenze.

Questo può essere utile se i tuoi documenti contengono dati non strutturati con campi diversi in gerarchie diverse. In questi casi, non c'è modo di prevedere quale dovrebbe essere l'indice, perché non si sa quali dati ci saranno in ciascun documento.

Gli indici con caratteri jolly possono essere utili con tali dati non strutturati, perché indicizzano tutti i valori scalari del campo, ricorrendo automaticamente in qualsiasi documento secondario o array e indicizzando tutti i campi scalari nel documento secondario/array.

Raccolta di esempi

Gli indici con caratteri jolly non sono per tutte le raccolte. Creeresti un indice jolly solo su determinate raccolte con documenti che contengono dati non strutturati con campi diversi in gerarchie diverse.

Di seguito è riportato un esempio di una collezione chiamata pets potrebbe essere un buon candidato per un indice jolly:

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

Ciascuno dei 3 documenti di questa raccolta ha un details campo, ma contengono campi diversi all'interno di quel campo. Non è coerente. Questo normalmente renderebbe difficile creare un indice, perché non sappiamo quali campi ci saranno in ogni documento. Probabilmente avremmo bisogno di creare più indici, dopo un'attenta analisi delle possibili strutture dei documenti.

Fortunatamente possiamo creare un indice con caratteri jolly.

Ma prima, diamo un'occhiata a come potrebbe apparire un piano di query quando si interroga uno di quei campi. Immagina di voler scoprire quale cane ha ottenuto il premio "Cane più veloce" alla Maratona di New York. Potremmo fare quanto segue:

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

E se volessimo controllare il piano di query, potremmo aggiungere explain() fino alla fine:

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

Che restituisce quanto segue:

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

Il che ci dice che stava per eseguire una scansione della raccolta (COLLSCAN), il che significa che deve scansionare ogni documento alla ricerca del campo.

Crea un indice di caratteri jolly

Ecco un esempio di creazione di un indice con caratteri jolly per la raccolta di cui sopra.

db.pets.createIndex({ "details.$**": 1 });

Uscita:

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

Questo è tutto. L'indice dei caratteri jolly è stato creato.

Per creare l'indice jolly abbiamo utilizzato il nome del campo su cui volevamo creare l'indice (in questo caso il details campo), quindi lo abbiamo aggiunto con un punto (. ), e poi la parte importante, il $** parte.

Il $** specifica che deve essere creato un indice con caratteri jolly da questo campo e tutti i relativi documenti secondari.

Prefisso il $** con details limita l'ambito dell'indice dei caratteri jolly ai soli details campo.

Ora ricontrolliamo il piano di query per la query di cui sopra:

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

Risultato:

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

Questa volta la scansione della raccolta (COLLSCAN) è stata sostituita da una scansione dell'indice (IXSCAN) sul nostro indice jolly appena creato.

Ogni campo all'interno dei nostri details il campo è stato indicizzato come percorso/valore e c'è una voce nell'indice per ogni campo nella gerarchia. Dove il valore del campo è un documento secondario (come il nostro. awards campo), l'indicizzazione è scesa nel documento secondario e ha ripetuto il processo.

Creazione di un indice di caratteri jolly su tutti i percorsi di campo

Nell'esempio precedente, abbiamo creato un indice con caratteri jolly su un percorso di campo singolo. È possibile creare un indice jolly su tutti i percorsi dei campi semplicemente utilizzando il $** senza anteporre un campo.

Ad esempio, avremmo potuto farlo:

db.pets.createIndex({ "$**": 1 });

Ciò avrebbe creato un indice di caratteri jolly su tutti i percorsi di campo.

In realtà, non è del tutto vero. Per impostazione predefinita, gli indici con caratteri jolly non vengono creati su _id campo. Per includere il _id campo, dovresti includerlo in un wildcardProjection documento.

Non riesci a creare indici con caratteri jolly? Controlla questa impostazione.

Il mongod featureCompatibilityVersion deve essere almeno 4.2 per creare indici con caratteri jolly.

Puoi controllare questa impostazione con il seguente codice:

db.adminCommand( 
    { 
        getParameter: 1, 
        featureCompatibilityVersion: 1 
    } 
)

Puoi impostarlo utilizzando setFeatureCompatibilityVersion comando:

db.adminCommand( { setFeatureCompatibilityVersion: "4.4" } )

Il setFeatureCompatibilityVersion il comando deve essere eseguito in admin banca dati.