sql >> Database >  >> NoSQL >> MongoDB

Maak een wildcard-index in MongoDB

Er zijn verschillende manieren om een ​​index te maken in MongoDB en vanaf MongoDB 4.2 kunnen we wildcard-indexen maken.

Een wildcard-index kan worden gezien als een soort filter dat automatisch overeenkomt met elk veld, subdocument of array in een verzameling en die overeenkomsten vervolgens indexeert.

Dit kan handig zijn als uw documenten ongestructureerde gegevens bevatten met verschillende velden in verschillende hiërarchieën. In dergelijke gevallen is er geen manier om te voorspellen wat de index zou moeten zijn, omdat u niet weet welke gegevens in elk document zullen staan.

Wildcard-indexen kunnen handig zijn bij dergelijke ongestructureerde gegevens, omdat ze alle scalaire waarden van het veld indexeren, automatisch terugkeren naar alle subdocumenten of arrays en alle scalaire velden in het subdocument/array indexeren.

Voorbeeldverzameling

Wildcard-indexen zijn niet voor elke verzameling. U zou alleen een wildcard-index maken voor bepaalde collecties met documenten die ongestructureerde gegevens bevatten met verschillende velden in verschillende hiërarchieën.

Hieronder ziet u een voorbeeld van een verzameling genaamd pets dat zou een goede kandidaat kunnen zijn voor een wildcard-index:

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

Elk van de 3 documenten in deze collectie heeft een details veld, maar ze bevatten verschillende velden binnen dat veld. Het is niet consistent. Dit zou het normaal gesproken moeilijk maken om een ​​index te maken, omdat we niet weten welke velden in elk document zullen staan. We zouden waarschijnlijk meerdere indexen moeten maken, na zorgvuldige analyse van de mogelijke documentstructuren.

Gelukkig kunnen we een wildcard-index maken.

Maar laten we eerst eens kijken hoe een queryplan eruit zou kunnen zien bij het opvragen van een van die velden. Stel je voor dat we willen weten welke hond de prijs "Snelste hond" heeft gekregen tijdens de marathon van New York. We zouden het volgende kunnen doen:

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

En als we het queryplan willen controleren, kunnen we explain() . toevoegen tot het einde:

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

Wat het volgende oplevert:

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

Dat vertelt ons dat het een collectiescan (COLLSCAN) ging doen, wat betekent dat het door elk document moet scannen op zoek naar het veld.

Maak een wildcard-index

Hier is een voorbeeld van het maken van een wildcard-index voor de bovenstaande verzameling.

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

Uitgang:

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

Dat is het. De wildcard-index is gemaakt.

Om de wildcard-index te maken, gebruikten we de veldnaam waarop we de index wilden maken (in dit geval de details veld), dan hebben we dat toegevoegd met een punt (. ), en dan het belangrijke deel, de $** onderdeel.

De $** geeft aan dat er een wildcard-index moet worden gemaakt op basis van dit veld en alle bijbehorende subdocumenten.

Voorvoegsel van de $** met details beperkt het bereik van de wildcard-index tot alleen de details veld.

Laten we nu het zoekplan voor de bovengenoemde zoekvraag opnieuw bekijken:

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

Resultaat:

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

Deze keer is de collectiescan (COLLSCAN) vervangen door een indexscan (IXSCAN) op onze nieuw aangemaakte wildcard-index.

Elk veld binnen onze details veld is geïndexeerd als een pad/waarde, en er is een vermelding in de index voor elk veld in de hiërarchie. Waar de veldwaarde een subdocument is (zoals onze. awards veld), is de indexering afgedaald in het subdocument en herhaalde het proces.

Een wildcard-index maken voor alle veldpaden

In het vorige voorbeeld hebben we een wildcard-index gemaakt op een enkel veldpad. Het is mogelijk om een ​​wildcard-index te maken voor alle veldpaden door simpelweg de $** . te gebruiken zonder het vooraf te laten gaan door een veld.

We hadden bijvoorbeeld dit kunnen doen:

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

Dat zou een wildcard-index hebben gecreëerd op alle veldpaden.

Eigenlijk is dat niet helemaal waar. Standaard worden er geen wildcard-indexen gemaakt op de _id veld. Om de _id . op te nemen veld, moet u het opnemen in een wildcardProjection document.

Kan geen wildcard-indexen maken? Vink deze instelling aan.

De mongod featureCompatibilityVersion moet minimaal 4.2 . zijn om wildcard-indexen te maken.

U kunt deze instelling controleren met de volgende code:

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

U kunt het instellen met behulp van de setFeatureCompatibilityVersion commando:

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

De setFeatureCompatibilityVersion commando moet worden uitgevoerd in de admin database.


  1. MongoDB geaggregeerde pijplijn traag na eerste matchstap

  2. MongoDB select count (distinct x) op een geïndexeerde kolom - tel unieke resultaten voor grote datasets

  3. Hoe de Redis-prestaties te verhogen bij 100% CPU? Scheren? Snelste .Net-client?

  4. Hoe MongoDB Java-stuurprogramma MongoOptions configureren voor productiegebruik?