Kiedy tworzysz indeks wieloznaczny w MongoDB, masz możliwość określenia pojedynczego pola, wszystkich pól lub tylko niektórych.
Możesz użyć wildcardProjection parametr, aby uwzględnić lub wykluczyć określone ścieżki pól z indeksu symboli wieloznacznych. W tym artykule przedstawiono przykład uwzględniania określonych pól w indeksie symboli wieloznacznych.
Przykładowy dokument
Załóżmy, że mamy kolekcję o nazwie pets z następującymi dokumentami:
{
"_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")
}
} Moglibyśmy utworzyć indeks wieloznaczny dla całej kolekcji, ale uwzględniać tylko te pola, które chcemy.
Utwórz indeks
Oto przykład:
db.pets.createIndex(
{ "$**" : 1 },
{
"wildcardProjection" : {
"details.type" : 1,
"details.born" : 1
}
}
) Wyjście:
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
{ "$**" : 1 } część tworzy indeks wieloznaczny, a wildcardProjection część to część określająca, które pola należy uwzględnić. W tym przypadku dołączyliśmy details.type pole i details.born pole. Nadając im wartość 1 wyraźnie uwzględnia je w indeksie.
Wyświetl indeks
Możemy wyświetlić indeksy w kolekcji, wywołując getIndexes() metoda:
db.pets.getIndexes() Wynik:
[
{
"v" : 2,
"key" : {
"_id" : 1
},
"name" : "_id_"
},
{
"v" : 2,
"key" : {
"$**" : 1
},
"name" : "$**_1",
"wildcardProjection" : {
"details.type" : 1,
"details.born" : 1
}
}
] Widzimy, że istnieją dwa indeksy.
- Pierwszy indeks znajduje się w
_idpole. Zostało to utworzone podczas tworzenia kolekcji (MongoDB tworzy unikalny indeks w polu _id podczas tworzenia kolekcji). - Drugi indeks to nasz indeks wieloznaczny. Widzimy, że został automatycznie nazwany
$**_1i zawiera określone przez nas pola.
Przetestuj indeks
Możemy również uruchomić kilka zapytań, aby sprawdzić, czy nasz indeks będzie używany, czy nie.
Teoretycznie następujące zapytanie powinno używać indeksu:
db.pets.find( { "details.type" : "Dog" } )
Aby to przetestować, możemy dołączyć explain() metoda przeglądania planu zapytań:
db.pets.find( { "details.type" : "Dog" } ).explain() Wynik:
{
"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
}
Widzimy, że użył skanowania indeksu (IXSCAN) w naszym indeksie.
W przeciwieństwie do tego, oto co się dzieje, gdy uruchamiamy zapytanie w polu, które nie zawarte w indeksie:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain() Wynik:
{
"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
} W tym przypadku wykonał skanowanie kolekcji (COLLSCAN), więc zgodnie z oczekiwaniami nie użył indeksu.