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
_id
pole. 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
$**_1
i 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.