sql >> Database teknologi >  >> NoSQL >> MongoDB

Opret et Multikey-indeks i MongoDB

I MongoDB, når du opretter et indeks på et felt, der indeholder et array, oprettes det automatisk som et multikey-indeks.

Multikey-indekser understøtter effektive forespørgsler mod matrixfelter.

Multikey-indekser kan oprettes for arrays, der indeholder skalære data (f.eks. strenge, tal osv.) og indlejrede dokumenter.

Eksempel

Antag, at vi har en samling kaldet products der indeholder følgende dokumenter:

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

Vi kan oprette et multinøgleindeks på den samling som dette:

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

Det er ligesom at oprette et almindeligt indeks. Du behøver ikke udtrykkeligt at angive, at det er et multikey-indeks. MongoDB er i stand til at bestemme, at feltet indeholder et array, og derfor oprette det som et multikey-indeks.

Med multikey-indekser opretter MongoDB en indeksnøgle for hvert element i arrayet.

Sammensat multinøgleindeks på indlejrede dokumenter

Som nævnt kan du oprette multikey-indekser for arrays, der indeholder indlejrede dokumenter.

Du kan oprette et sammensat indeks på disse, så dit indeks oprettes mod flere felter i arrayet.

Antag, at vi har en samling kaldet restaurants med dokumenter som dette:

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

Vi kunne oprette et sammensat multikey-indeks som dette:

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

Nu vil multikey-indekset blive brugt, når vi kører forespørgsler, der involverer disse felter.

Sådan ser forespørgselsplanen ud, når vi søger mod et af disse felter:

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

Resultat:

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

Den del, der læser IXSCAN betyder, at den foretog en indeksscanning. Hvis den ikke havde brugt indekset, ville den have lavet en indsamlingsscanning (COLLSCAN ).

Det er det samme, når vi laver en forespørgsel, der involverer begge felter i indekset:

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

Resultat:

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

Men hvis et af felterne i forespørgslen ikke er inkluderet i indekset, resulterer det i en samlingsscanning:

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

Resultat:

{
	"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. Hvordan kan jeg trække underdokumenter fra et array?

  2. Hvordan konfigureres Redis-forbindelser med Rails 4, Puma og Sidekiq?

  3. Klon en samling i MongoDB

  4. Hvordan deler man session mellem NodeJs og PHP ved hjælp af Redis?