MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Erstellen Sie einen Wildcard-Index in MongoDB

Es gibt mehrere Möglichkeiten, einen Index in MongoDB zu erstellen, und ab MongoDB 4.2 können wir Wildcard-Indizes erstellen.

Ein Wildcard-Index kann als eine Art Filter betrachtet werden, der automatisch alle Felder, Unterdokumente oder Arrays in einer Sammlung abgleicht und diese Übereinstimmungen dann indiziert.

Dies kann nützlich sein, wenn Ihre Dokumente unstrukturierte Daten mit unterschiedlichen Feldern in unterschiedlichen Hierarchien enthalten. In solchen Fällen gibt es keine Möglichkeit vorherzusagen, was der Index sein sollte, da Sie nicht wissen, welche Daten in jedem Dokument enthalten sein werden.

Wildcard-Indizes können bei solchen unstrukturierten Daten nützlich sein, da sie alle Skalarwerte des Felds indizieren, automatisch in alle Unterdokumente oder Arrays rekursiv gehen und alle Skalarfelder im Unterdokument/Array indizieren.

Beispielsammlung

Wildcard-Indizes sind nicht für jede Sammlung geeignet. Sie würden einen Wildcard-Index nur für bestimmte Sammlungen mit Dokumenten erstellen, die unstrukturierte Daten mit unterschiedlichen Feldern in unterschiedlichen Hierarchien enthalten.

Unten sehen Sie ein Beispiel für eine Sammlung namens pets das könnte ein guter Kandidat für einen Wildcard-Index sein:

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

Jedes der 3 Dokumente in dieser Sammlung hat einen details Feld, aber sie enthalten andere Felder innerhalb dieses Feldes. Es ist nicht konsistent. Dies würde es normalerweise schwierig machen, einen Index zu erstellen, da wir nicht wissen, welche Felder in jedem Dokument enthalten sein werden. Nach sorgfältiger Analyse der möglichen Dokumentstrukturen müssten wir wahrscheinlich mehrere Indizes erstellen.

Glücklicherweise können wir einen Wildcard-Index erstellen.

Aber lassen Sie uns zunächst einen Blick darauf werfen, wie ein Abfrageplan aussehen könnte, wenn eines dieser Felder abgefragt wird. Stellen Sie sich vor, wir möchten herausfinden, welcher Hund beim New York Marathon die Auszeichnung „Schnellster Hund“ erhalten hat. Wir könnten Folgendes tun:

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

Und wenn wir den Abfrageplan überprüfen wollten, könnten wir explain() anhängen zum Ende:

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

Was Folgendes zurückgibt:

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

Was uns sagt, dass es einen Sammlungsscan (COLLSCAN) durchführen würde, was bedeutet, dass es jedes Dokument durchsuchen muss, um nach dem Feld zu suchen.

Erstellen Sie einen Wildcard-Index

Hier ist ein Beispiel für die Erstellung eines Wildcard-Index für die obige Sammlung.

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

Ausgabe:

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

Das ist es. Der Wildcard-Index wurde erstellt.

Um den Wildcard-Index zu erstellen, haben wir den Feldnamen verwendet, für den wir den Index erstellen wollten (in diesem Fall die details Feld), dann haben wir das mit einem Punkt angehängt (. ) und dann der wichtige Teil, der $** Teil.

Der $** gibt an, dass aus diesem Feld und allen seinen Unterdokumenten ein Platzhalterindex erstellt werden soll.

Dem $** voranstellen mit details beschränkt den Geltungsbereich des Wildcard-Index auf die details Feld.

Lassen Sie uns nun den Abfrageplan für die oben genannte Abfrage erneut überprüfen:

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

Ergebnis:

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

Diesmal wurde der Sammlungs-Scan (COLLSCAN) durch einen Index-Scan (IXSCAN) auf unserem neu erstellten Wildcard-Index ersetzt.

Jedes Feld in unseren details Feld wurde als Pfad/Wert indiziert, und es gibt einen Eintrag im Index für jedes Feld in der Hierarchie. Wobei der Feldwert ein untergeordnetes Dokument ist (z. B. unsere. awards Feld), ist die Indizierung in das Filialdokument heruntergekommen und hat den Vorgang wiederholt.

Erstellen eines Wildcard-Index für alle Feldpfade

Im vorherigen Beispiel haben wir einen Platzhalterindex für einen einzelnen Feldpfad erstellt. Es ist möglich, einen Wildcard-Index für alle Feldpfade zu erstellen, indem Sie einfach den $** verwenden ohne ihm ein Feld voranzustellen.

Zum Beispiel hätten wir Folgendes tun können:

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

Das hätte einen Wildcard-Index auf allen Feldpfaden erzeugt.

Eigentlich stimmt das nicht ganz. Standardmäßig werden Wildcard-Indizes nicht auf der _id erstellt Feld. Zum Einschließen der _id Feld, müssten Sie es in eine wildcardProjection einfügen Dokument.

Platzhalter-Indizes können nicht erstellt werden? Überprüfen Sie diese Einstellung.

Der mongod featureCompatibilityVersion muss mindestens 4.2 sein Wildcard-Indizes zu erstellen.

Sie können diese Einstellung mit dem folgenden Code überprüfen:

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

Sie können es mit setFeatureCompatibilityVersion festlegen Befehl:

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

Die setFeatureCompatibilityVersion Der Befehl muss im admin ausgeführt werden Datenbank.