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.