sql >> Databasteknik >  >> NoSQL >> MongoDB

Skapa ett jokerteckenindex i MongoDB

Det finns flera sätt att skapa ett index i MongoDB, och från MongoDB 4.2 kan vi skapa jokerteckenindex.

Ett jokerteckenindex kan ses som ett slags filter som automatiskt matchar alla fält, underdokument eller matriser i en samling och sedan indexerar dessa matchningar.

Detta kan vara användbart om dina dokument innehåller ostrukturerade data med olika fält i olika hierarkier. I sådana fall finns det inget sätt att förutsäga vad indexet ska vara, eftersom du inte vet vilken data som kommer att finnas i varje dokument.

Jokerteckenindex kan vara användbara med sådan ostrukturerad data, eftersom de indexerar alla skalära värden i fältet, automatiskt återkommer i alla underdokument eller arrayer och indexerar alla skalära fält i underdokumentet/arrayen.

Exempelsamling

Jokertecken-index är inte för varje samling. Du skulle bara skapa ett jokertecken på vissa samlingar med dokument som innehåller ostrukturerade data med olika fält i olika hierarkier.

Nedan är ett exempel på en samling som heter pets som kan vara en bra kandidat för ett jokertecken:

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

Vart och ett av de tre dokumenten i denna samling har en details fältet, men de innehåller olika fält inom det fältet. Det är inte konsekvent. Detta skulle normalt göra det svårt att skapa ett index, eftersom vi inte vet vilka fält som kommer att finnas i varje dokument. Vi skulle förmodligen behöva skapa flera index, efter noggrann analys av de möjliga dokumentstrukturerna.

Lyckligtvis kan vi skapa ett jokertecken.

Men först, låt oss ta en titt på hur en frågeplan kan se ut när du frågar ett av dessa fält. Föreställ dig att vi vill ta reda på vilken hund som fick priset "Snabbaste hund" vid New York Marathon. Vi skulle kunna göra följande:

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

Och om vi vill kontrollera frågeplanen kan vi lägga till explain() till slutet:

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

Vilket returnerar följande:

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

Vilket talar om för oss att den skulle göra en samlingsskanning (COLLSCAN), vilket innebär att den måste skanna igenom varje dokument som letar efter fältet.

Skapa ett jokerteckenindex

Här är ett exempel på hur du skapar ett jokertecken för ovanstående samling.

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

Utdata:

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

Det är allt. Jokerteckenindexet har skapats.

För att skapa jokerteckenindexet använde vi fältnamnet som vi ville skapa indexet på (i det här fallet details fältet), sedan lade vi till det med en punkt (. ), och sedan den viktiga delen, $** del.

$** anger att ett jokertecken ska skapas från detta fält och alla dess underdokument.

Prefixet $** med details begränsar jokerteckenindexets omfattning till bara details fältet.

Låt oss nu kontrollera frågeplanen för den ovannämnda frågan:

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

Den här gången har samlingsskanningen (COLLSCAN) ersatts av en indexskanning (IXSCAN) på vårt nyskapade jokerteckenindex.

Varje fält i våra details fältet har indexerats som en sökväg/värde, och det finns en post i indexet för varje fält i hierarkin. Där fältvärdet är ett underdokument (som våra. awards). fältet), har indexeringen gått ner i underdokumentet och upprepat processen.

Skapa ett jokerteckenindex på alla fältsökvägar

I det föregående exemplet skapade vi ett jokertecken på en enda fältsökväg. Det är möjligt att skapa ett jokertecken på alla fältsökvägar helt enkelt genom att använda $** utan att prefixet det med ett fält.

Vi kunde till exempel ha gjort detta:

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

Det skulle ha skapat ett jokertecken på alla fältsökvägar.

Egentligen är det inte riktigt sant. Som standard skapas inte jokerteckenindex på _id fält. För att inkludera _id fältet måste du inkludera det i en wildcardProjection dokument.

Kan du inte skapa jokertecken? Kontrollera den här inställningen.

mongod featureCompatibilityVersion måste vara minst 4.2 för att skapa jokertecken.

Du kan kontrollera denna inställning med följande kod:

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

Du kan ställa in den med setFeatureCompatibilityVersion kommando:

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

setFeatureCompatibilityVersion kommandot måste köras i admin databas.


  1. Buffrad dataanvändning för överflödessorteringssteg överskrider den interna gränsen

  2. Spark HBase Connector – ett år i översyn

  3. Konfigurera ElastiCache Redis med Elastic Beanstalk + Django

  4. Hur tar man bort ett fält helt från ett MongoDB-dokument?