Du kan tænke på MongoDB enkeltfeltsindeks som et array med pointere til dokumentplaceringer. For eksempel, hvis du har en samling med (bemærk, at sekvensen bevidst er ude af rækkefølge):
[collection]
1: {a:3, b:2}
2: {a:1, b:2}
3: {a:2, b:1}
4: {a:1, b:1}
5: {a:2, b:2}
Enkeltfeltsindeks
Hvis du nu gør det:
db.collection.createIndex({a:1})
Indekset ser omtrent sådan ud:
[index a:1]
1: {a:1} --> 2, 4
2: {a:2} --> 3, 5
3: {a:3} --> 1
Bemærk tre vigtige ting:
- Det er sorteret efter
a
stigende - Hver indtastning peger på det sted, hvor de relevante dokumenter ligger
- Indekset registrerer kun værdierne af
a
Mark.b
felt findes slet ikke i indekset
Så hvis du laver en forespørgsel som:
db.collection.find().sort({a:1})
Alt det skal gøre er at gå indekset fra top til bund, hente og udskrive det dokument, som indtastningerne peger på. Bemærk, at du også kan gå i indekset fra bunden, f.eks.:
db.collection.find().sort({a:-1})
og den eneste forskel er, at du går indekset omvendt.
Fordi b
er slet ikke i indekset, kan du ikke bruge indekset, når du forespørger noget om b
.
Sammensat indeks
I et sammensat indeks f.eks.:
db.collection.createIndex({a:1, b:1})
Det betyder, at du vil sortere efter a
først, sorter derefter efter b
. Indekset ville se sådan ud:
[index a:1, b:1]
1: {a:1, b:1} --> 4
2: {a:1, b:2} --> 2
3: {a:2, b:1} --> 3
4: {a:2, b:2} --> 5
5: {a:3, b:2} --> 1
Bemærk at:
- Indekset er sorteret fra
a
- Inden for hver
a
du har en sorteretb
- Du har 5 indeksindgange i forhold til kun tre i det foregående enkeltfeltseksempel
Ved at bruge dette indeks kan du lave en forespørgsel som:
db.collection.find({a:2}).sort({b:1})
Det kan nemt finde hvor a:2
gå derefter indekset frem. I betragtning af det indeks kan du ikke gøre det :
db.collection.find().sort({b:1})
db.collection.find({b:1})
I begge forespørgsler kan du ikke nemt finde b
da det er spredt over hele indekset (dvs. ikke i sammenhængende poster). Men du kan gør:
db.collection.find({a:2}).sort({b:-1})
da du i det væsentlige kan finde hvor a:2
er, og gå b
indtastninger baglæns.
Rediger :præcisering af @marcospgps spørgsmål i kommentaren:
Muligheden for at bruge indekset {a:1, b:1}
for at tilfredsstille find({a:2}).sort({b:-1})
giver faktisk mening, hvis du ser det fra et sorteret bordsynspunkt. For eksempel indekset {a:1, b:1}
kan opfattes som:
a | b
--|--
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2
find({a:2}).sort({b:1})
Indekset {a:1, b:1}
betyder sort by a, then within each a, sort the b values
. Hvis du derefter laver en find({a:2}).sort({b:1})
, indekset ved, hvor alle a=2
er. Inden for denne blok af a=2
, b
ville blive sorteret i stigende rækkefølge (i henhold til indeksspecifikationen), så forespørgslen find({a:2}).sort({b:1})
kan tilfredsstilles ved:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block forward to satisfy
2 | 2 <-- find({a:2}).sort({b:1})
2 | 3 <--
3 | 1
3 | 2
find({a:2}).sort({b:-1})
Da indekset kan gås frem eller tilbage, blev en lignende procedure fulgt, med en lille drejning i slutningen:
a | b
--|--
1 | 1
1 | 2
2 | 1 <-- walk this block backward to satisfy
2 | 2 <-- find({a:2}).sort({b:-1})
2 | 3 <--
3 | 1
3 | 2
Det faktum, at indekset kan gås frem eller tilbage, er nøglepunktet, der aktiverer forespørgslen find({a:2}).sort({b:-1})
for at kunne bruge indekset {a:1, b:1}
.
Forklaring af forespørgselsplanlægning
Du kan se, hvad forespørgselsplanlæggeren planlægger ved at bruge db.collection.explain().find(....)
. Grundlæggende hvis du ser et stage
af COLLSCAN
, intet indeks blev brugt eller kan bruges til forespørgslen. Se forklar resultater
for detaljer om kommandoens output.