När du skapar ett jokertecken i MongoDB har du möjlighet att ange ett enda fält, alla fält eller bara några.
Du kan använda wildcardProjection
parameter för att inkludera eller exkludera specifika fältsökvägar från jokerteckenindexet. Den här artikeln presenterar ett exempel på att inkludera specifika fält i jokerteckenindexet.
Exempeldokument
Anta att vi har en samling som heter pets
med följande dokument:
{ "_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") } }
Vi skulle kunna skapa ett jokertecken på hela samlingen, men bara inkludera de fält vi vill ha.
Skapa indexet
Här är ett exempel:
db.pets.createIndex(
{ "$**" : 1 },
{
"wildcardProjection" : {
"details.type" : 1,
"details.born" : 1
}
}
)
Utdata:
{ "createdCollectionAutomatically" : false, "numIndexesBefore" : 1, "numIndexesAfter" : 2, "ok" : 1 }
{ "$**" : 1 }
del är det som skapar jokerteckenindexet och wildcardProjection
del är den del som anger vilka fält som ska inkluderas. I det här fallet har vi inkluderat details.type
och details.born
fält. Ge dem värdet 1
inkluderar dem uttryckligen i indexet.
Visa indexet
Vi kan se indexen på samlingen genom att anropa getIndexes()
metod:
db.pets.getIndexes()
Resultat:
[ { "v" : 2, "key" : { "_id" : 1 }, "name" : "_id_" }, { "v" : 2, "key" : { "$**" : 1 }, "name" : "$**_1", "wildcardProjection" : { "details.type" : 1, "details.born" : 1 } } ]
Vi kan se att det finns två index.
- Det första indexet finns på
_id
fält. Detta skapades när samlingen skapades (MongoDB skapar ett unikt index på _id-fältet under skapandet av en samling). - Det andra indexet är vårt jokertecken. Vi kan se att den automatiskt har fått namnet
$**_1
, och det inkluderar fälten som vi angav.
Testa indexet
Vi kan också köra några frågor för att se om vårt index kommer att användas eller inte.
I teorin bör följande fråga använda indexet:
db.pets.find( { "details.type" : "Dog" } )
För att testa detta kan vi lägga till explain()
metod för att visa frågeplanen:
db.pets.find( { "details.type" : "Dog" } ).explain()
Resultat:
{ "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 }
Vi kan se att den använde en indexskanning (IXSCAN) på vårt index.
I motsats till detta, här är vad som händer när vi kör en fråga på ett fält som inte ingår i indexet:
db.pets.find( { "details.awards.New York Marathon" : "Fastest Dog" } ).explain()
Resultat:
{ "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 }
I det här fallet gjorde den en samlingsskanning (COLLSCAN), så som förväntat använde den inte indexet.