sql >> Database >  >> NoSQL >> MongoDB

Maak een Multikey Index in MongoDB

Wanneer u in MongoDB een index maakt op een veld dat een array bevat, wordt deze automatisch gemaakt als een index met meerdere toetsen.

Multikey-indexen ondersteunen efficiënte zoekopdrachten voor arrayvelden.

Multikey-indexen kunnen worden gemaakt voor arrays die scalaire gegevens bevatten (bijvoorbeeld tekenreeksen, getallen, enz.) en geneste documenten.

Voorbeeld

Stel dat we een verzameling hebben met de naam products die de volgende documenten bevat:

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

We kunnen een multikey-index voor die verzameling als volgt maken:

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

Het is net als het maken van een gewone index. U hoeft niet expliciet aan te geven dat het een index met meerdere toetsen is. MongoDB kan bepalen dat het veld een array bevat en het daarom maken als een index met meerdere sleutels.

Met multikey-indexen maakt MongoDB een indexsleutel voor elk element in de array.

Samengestelde multikey-index op ingesloten documenten

Zoals vermeld, kunt u indexen met meerdere sleutels maken voor arrays die ingesloten documenten bevatten.

U kunt hierop een samengestelde index maken, zodat uw index wordt gemaakt voor meerdere velden in de array.

Stel dat we een verzameling hebben met de naam restaurants met documenten zoals deze:

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
      }]
   }
])

We zouden een samengestelde multikey-index als volgt kunnen maken:

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

Nu wordt de multikey-index gebruikt wanneer we query's uitvoeren die betrekking hebben op die velden.

Zo ziet het zoekplan eruit als we op een van die velden zoeken:

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

Resultaat:

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

Het deel dat IXSCAN . leest betekent dat het een indexscan heeft uitgevoerd. Als het de index niet had gebruikt, zou het een collectiescan hebben gedaan (COLLSCAN ).

Het is hetzelfde als we een zoekopdracht uitvoeren waarbij beide velden in de index betrokken zijn:

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

Resultaat:

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

Als een van de velden in de zoekopdracht echter niet in de index is opgenomen, resulteert dit in een collectiescan:

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

Resultaat:

{
	"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. Mongoose/mongoDB-query voegt zich bij ... maar ik kom uit een sql-achtergrond

  2. Hoe de lokale Mongo-database te verbinden met docker

  3. Over MongoDB

  4. het MongoDB-cachesysteem begrijpen