MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Utwórz indeks wieloznaczny w MongoDB

Istnieje kilka sposobów tworzenia indeksu w MongoDB, a od MongoDB 4.2 możemy tworzyć indeksy wieloznaczne.

Indeks wieloznaczny można traktować jako rodzaj filtra, który automatycznie dopasowuje dowolne pole, dokument podrzędny lub tablicę w kolekcji, a następnie indeksuje te dopasowania.

Może to być przydatne, jeśli dokumenty zawierają nieustrukturyzowane dane z różnymi polami w różnych hierarchiach. W takich przypadkach nie ma możliwości przewidzenia, jaki powinien być indeks, ponieważ nie wiadomo, jakie dane będą w każdym dokumencie.

Indeksy wieloznaczne mogą być przydatne w przypadku takich nieustrukturyzowanych danych, ponieważ indeksują wszystkie wartości skalarne pola, automatycznie rekursując się w dowolne poddokumenty lub tablice i indeksując wszystkie pola skalarne w poddokumencie/tablicy.

Przykładowa kolekcja

Indeksy wieloznaczne nie dotyczą każdej kolekcji. Utworzyłbyś indeks wieloznaczny tylko w niektórych kolekcjach z dokumentami, które zawierają nieustrukturyzowane dane z różnymi polami w różnych hierarchiach.

Poniżej znajduje się przykład kolekcji o nazwie pets to może być dobrym kandydatem na indeks wieloznaczny:

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

Każdy z 3 dokumentów w tej kolekcji ma details pola, ale zawierają różne pola w tym polu. To nie jest spójne. Normalnie utrudniłoby to utworzenie indeksu, ponieważ nie wiemy, jakie pola będą znajdować się w każdym dokumencie. Prawdopodobnie musielibyśmy utworzyć wiele indeksów po dokładnej analizie możliwych struktur dokumentów.

Na szczęście możemy stworzyć indeks wieloznaczny.

Ale najpierw przyjrzyjmy się, jak może wyglądać plan zapytania podczas wykonywania zapytania w jednym z tych pól. Wyobraź sobie, że chcemy dowiedzieć się, który pies otrzymał nagrodę „Najszybszy pies” podczas Maratonu Nowojorskiego. Moglibyśmy wykonać następujące czynności:

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

A gdybyśmy chcieli sprawdzić plan zapytania, moglibyśmy dołączyć explain() do końca:

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

Co zwraca następujące informacje:

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

Co mówi nam, że zamierzał wykonać skanowanie kolekcji (COLLSCAN), co oznacza, że ​​musi przeskanować każdy dokument w poszukiwaniu pola.

Utwórz indeks wieloznaczny

Oto przykład tworzenia indeksu wieloznacznego dla powyższej kolekcji.

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

Wyjście:

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

Otóż ​​to. Utworzono indeks wieloznaczny.

Aby utworzyć indeks wieloznaczny, użyliśmy nazwy pola, dla którego chcieliśmy utworzyć indeks (w tym przypadku details pole), następnie dodaliśmy kropkę (. ), a następnie ważna część, $** część.

$** określa, że ​​indeks wieloznaczny powinien zostać utworzony z tego pola i wszystkich jego dokumentów podrzędnych.

Przedrostek $** ze details ogranicza zakres indeksu symboli wieloznacznych tylko do details pole.

Teraz sprawdźmy ponownie plan zapytań dla powyższego zapytania:

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

Tym razem skanowanie kolekcji (COLLSCAN) zostało zastąpione skanowaniem indeksu (IXSCAN) naszego nowo utworzonego indeksu symboli wieloznacznych.

Każde pole w naszych details pole zostało zindeksowane jako ścieżka/wartość, aw indeksie znajduje się wpis dla każdego pola w hierarchii. Gdzie wartość pola jest dokumentem podrzędnym (takim jak nasz. awards pole), indeksowanie zeszło do poddokumentu i powtórzyło proces.

Tworzenie indeksu wieloznacznego na wszystkich ścieżkach pól

W poprzednim przykładzie utworzyliśmy indeks wieloznaczny na pojedynczej ścieżce pola. Możliwe jest utworzenie indeksu wieloznacznego na wszystkich ścieżkach pól, po prostu za pomocą $** bez poprzedzania go polem.

Na przykład moglibyśmy to zrobić:

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

To spowodowałoby utworzenie indeksu wieloznacznego we wszystkich ścieżkach pól.

Właściwie to nie do końca prawda. Domyślnie indeksy wieloznaczne nie są tworzone w _id pole. Aby uwzględnić _id pole, musisz uwzględnić je w wildcardProjection dokument.

Nie możesz tworzyć indeksów wieloznacznych? Sprawdź to ustawienie.

mongod featureCompatibilityVersion musi mieć co najmniej 4.2 do tworzenia indeksów z symbolami wieloznacznymi.

Możesz sprawdzić to ustawienie za pomocą następującego kodu:

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

Możesz to ustawić za pomocą setFeatureCompatibilityVersion polecenie:

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

setFeatureCompatibilityVersion polecenie musi być uruchomione w admin baza danych.


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Wymuszanie kontroli dostępu opartej na rolach za pomocą ClusterControl

  2. Jak mogę zaimplementować uprawnienia na poziomie pola dla MongoDB?

  3. Zaktualizuj osadzony obiekt wewnątrz tablicy wewnątrz tablicy w MongoDB

  4. Dlaczego mongoose używa schematu, kiedy zaletą mongodb jest to, że jest pozbawiony schematu?

  5. 4 sposoby na aktualizację dokumentu w MongoDB