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

Utwórz indeks wielokluczowy w MongoDB

W MongoDB, kiedy tworzysz indeks w polu zawierającym tablicę, jest on automatycznie tworzony jako indeks wielokluczowy.

Indeksy wielokluczowe obsługują wydajne zapytania dotyczące pól tablicy.

Indeksy wielokluczowe można tworzyć dla tablic, które przechowują dane skalarne (np. ciągi, liczby itp.) i zagnieżdżone dokumenty.

Przykład

Załóżmy, że mamy kolekcję o nazwie products który zawiera następujące dokumenty:

{ "_id" : 1, "product" : "Bat", "sizes" : [ "S", "M", "L" ] }
{ "_id" : 2, "product" : "Hat", "sizes" : [ "S", "L", "XL" ] }
{ "_id" : 3, "product" : "Cap", "sizes" : [ "M", "L" ] }

Możemy utworzyć indeks wielokluczowy dla tej kolekcji w ten sposób:

db.products.createIndex(
   {
     "sizes": 1
   }
)

To tak, jak tworzenie zwykłego indeksu. Nie musisz wyraźnie określać, że jest to indeks wielokluczowy. MongoDB jest w stanie określić, że pole zawiera tablicę, a zatem utworzyć ją jako indeks wielokluczowy.

W przypadku indeksów wielokluczowych MongoDB tworzy klucz indeksu dla każdego elementu tablicy.

Złożony indeks wielokluczowy w osadzonych dokumentach

Jak wspomniano, możesz tworzyć indeksy wielokluczowe dla tablic zawierających osadzone dokumenty.

Możesz utworzyć dla nich indeks złożony, dzięki czemu Twój indeks zostanie utworzony dla wielu pól w tablicy.

Załóżmy, że mamy kolekcję o nazwie restaurants z takimi dokumentami:

db.restaurants.insertMany([
   {
    _id: 1,
    name: "The Rat",
    reviews: [{
        name: "Stanley",
        date: "04 December, 2020",
        ordered: "Dinner",
        rating: 1
      },
      {
        name: "Tom",
        date: "04 October, 2020",
        ordered: "Lunch",
        rating: 2
      }]
   },
   {
    _id: 2,
    name: "Yum Palace",
    reviews: [{
        name: "Stacey",
        date: "08 December, 2020",
        ordered: "Lunch",
        rating: 3
      },
      {
        name: "Tom",
        date: "08 October, 2020",
        ordered: "Breakfast",
        rating: 4
      }]
   },
   {
    _id: 3,
    name: "Boardwalk Cafe",
    reviews: [{
        name: "Steve",
        date: "20 December, 2020",
        ordered: "Breakfast",
        rating: 5
      },
      {
        name: "Lisa",
        date: "25 October, 2020",
        ordered: "Dinner",
        rating: 5
      },
      {
        name: "Kim",
        date: "21 October, 2020",
        ordered: "Dinner",
        rating: 5
      }]
   }
])

Możemy utworzyć złożony indeks wielokluczowy w następujący sposób:

db.restaurants.createIndex( 
  { 
    "reviews.ordered": 1,
    "reviews.rating": -1
  } 
)

Teraz indeks wielokluczowy będzie używany za każdym razem, gdy uruchamiamy zapytania obejmujące te pola.

Oto, jak wygląda plan zapytań, gdy szukamy w jednym z tych pól:

db.restaurants.find( { "reviews.ordered": "Dinner" } ).explain()

Wynik:

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "krankykranes.restaurants",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"reviews.ordered" : {
				"$eq" : "Dinner"
			}
		},
		"queryHash" : "A01226B4",
		"planCacheKey" : "0E761583",
		"winningPlan" : {
			"stage" : "FETCH",
			"inputStage" : {
				"stage" : "IXSCAN",
				"keyPattern" : {
					"reviews.ordered" : 1,
					"reviews.rating" : -1
				},
				"indexName" : "reviews.ordered_1_reviews.rating_-1",
				"isMultiKey" : true,
				"multiKeyPaths" : {
					"reviews.ordered" : [
						"reviews"
					],
					"reviews.rating" : [
						"reviews"
					]
				},
				"isUnique" : false,
				"isSparse" : false,
				"isPartial" : false,
				"indexVersion" : 2,
				"direction" : "forward",
				"indexBounds" : {
					"reviews.ordered" : [
						"[\"Dinner\", \"Dinner\"]"
					],
					"reviews.rating" : [
						"[MaxKey, MinKey]"
					]
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"ok" : 1
}

Część, która czyta IXSCAN oznacza, że ​​wykonał skanowanie indeksu. Gdyby nie używał indeksu, wykonałby skanowanie kolekcji (COLLSCAN ).

Tak samo jest, gdy wykonujemy zapytanie, które obejmuje oba pola w indeksie:

db.restaurants.find( { "reviews.ordered": "Dinner", "reviews.rating": { $gt: 3 } } ).explain()

Wynik:

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "krankykranes.restaurants",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"$and" : [
				{
					"reviews.ordered" : {
						"$eq" : "Dinner"
					}
				},
				{
					"reviews.rating" : {
						"$gt" : 3
					}
				}
			]
		},
		"queryHash" : "C770E210",
		"planCacheKey" : "447B5666",
		"winningPlan" : {
			"stage" : "FETCH",
			"filter" : {
				"reviews.rating" : {
					"$gt" : 3
				}
			},
			"inputStage" : {
				"stage" : "IXSCAN",
				"keyPattern" : {
					"reviews.ordered" : 1,
					"reviews.rating" : -1
				},
				"indexName" : "reviews.ordered_1_reviews.rating_-1",
				"isMultiKey" : true,
				"multiKeyPaths" : {
					"reviews.ordered" : [
						"reviews"
					],
					"reviews.rating" : [
						"reviews"
					]
				},
				"isUnique" : false,
				"isSparse" : false,
				"isPartial" : false,
				"indexVersion" : 2,
				"direction" : "forward",
				"indexBounds" : {
					"reviews.ordered" : [
						"[\"Dinner\", \"Dinner\"]"
					],
					"reviews.rating" : [
						"[MaxKey, MinKey]"
					]
				}
			}
		},
		"rejectedPlans" : [ ]
	},
	"ok" : 1
}

Jeśli jednak jedno z pól w zapytaniu nie jest uwzględnione w indeksie, to powoduje to skanowanie kolekcji:

db.restaurants.find( { "reviews.name": "Lisa", "reviews.rating": { $gt: 3 } } ).explain()

Wynik:

{
	"queryPlanner" : {
		"plannerVersion" : 1,
		"namespace" : "krankykranes.restaurants",
		"indexFilterSet" : false,
		"parsedQuery" : {
			"$and" : [
				{
					"reviews.name" : {
						"$eq" : "Lisa"
					}
				},
				{
					"reviews.rating" : {
						"$gt" : 3
					}
				}
			]
		},
		"queryHash" : "49EF83EC",
		"planCacheKey" : "3C60321C",
		"winningPlan" : {
			"stage" : "COLLSCAN",
			"filter" : {
				"$and" : [
					{
						"reviews.name" : {
							"$eq" : "Lisa"
						}
					},
					{
						"reviews.rating" : {
							"$gt" : 3
						}
					}
				]
			},
			"direction" : "forward"
		},
		"rejectedPlans" : [ ]
	},
	"ok" : 1
}


  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak utworzyć indeks zagnieżdżony w MongoDB?

  2. za dużo otwartych plików na serwerze mgo go

  3. Mongoose - spowodowane przez ::11000 E11000 zduplikowany indeks błędu klucza?

  4. MongoDB — Utwórz bazę danych

  5. Zapytanie o dokument i wszystkie jego dokumenty podrzędne, które pasują do warunku w mongodb (przy użyciu wiosny)