Programmering

MongoDB primærnøkler er din venn

Alle dokumenter i en MongoDB-samling har en primærnøkkel _id. Dette feltet tildeles automatisk et dokument ved innsetting, så det er sjelden behov for å oppgi det. Hva er interessant med _id feltet er at det er tidsbasert. Det vil si den underliggende typen _id, som er ObjectId, er en 12-byte BSON-type, og 4 av disse bytene representerer sekundene siden Unix-epoken.

Det som også er spesielt med _id feltet er at det automatisk indekseres som du kan se nedenfor ved å ringe getIndexes på enhver samling.

1 2 3 4 5 6 7 8 9 10 11 
> db.things.getIndexes () [{"v": 1, "key": {"_id": 1}, "ns": "test.things", "name": "_id_"}] 

Og som alle husker fra tradisjonelle RDBMS-er, er indekser viktige fordi de kan gjøre dokumentinnhenting raskere; likevel bruker indekser minne og det er en liten ytelsesstraff når du setter inn dokumenter, ettersom alle tilsvarende indekser må oppdateres. Så selv om du seriøst bør vurdere å bruke indekser, må du være økonomisk i bruken.

Naturligvis søker etter et dokument _id er bare praktisk når du vet den. Oftere enn ikke blir det søkt i dokumenter via andre felt, og hvis du finner deg selv i å søke via en tidsserie, for eksempel opprettet_på så er du inne for en godbit.

Tenk deg en samling kalt tømmerstokker som inneholder enkle dokumenter som fanger opp forskjellige loggmeldinger. Et eksempeldokument kan se slik ut:

1 2 3 4 5 6 
{"_id": ObjectId ("51c4ab6d4d6906d494460728"), "message": "crashed, no such method exception", "type": "crash", "created_at": ISODate ("2013-06-21T19: 37: 17.992Z ")} 

Hva om jeg ville finne alle loggmeldinger for en dato, som i dag? Jeg kunne skrevet spørringen min slik:

1 
db.logs.find ({created_at: {'$ gt': new Date (2013, 5, 20)}}) 

Hvis jeg kaster en forklaring på spørringen, kan jeg se det fordi jeg ikke har en indeks på opprettet_på, er en grunnleggende markør utnyttet og alle dokumenter i samlingen ble skannet for å hente resultatet mitt.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 
> db.logs.find ({created_at: {'$ gt': new Date (2013, 5, 20)}}). forklar () {"cursor": "BasicCursor", "isMultiKey": false, "n" : 2, "nscannedObjects": 4, "nscanned": 4, "nscannedObjectsAllPlans": 4, "nscannedAllPlans": 4, "scanAndOrder": false, "indexOnly": false, "nYields": 0, "nChunkSkips": 0 , "millis": 0, "indexBounds": {}, "server": "ghome-computer.home: 27017"} 

Som du kan se, søker du via opprettet_på felt kan være ineffektivt; dermed kan du bli fristet til å kaste en indeks på det feltet. Dette vil naturligvis gjøre det aktuelle spørsmålet mer effektivt, men du vil pådra deg kostnadene for en ny indeks som er mer lagret i minnet, og innleggene vil være litt tregere på grunn av en oppdatering til den nyopprettede indeksen.

Som det viser seg, fordi _id felt innebærer Unix-epoke i den, kan du like gjerne lage et finnuttrykk uten inkludert opprettet_på felt. For eksempel lar MongoDB Ruby-driveren deg lage ObjectIdEr fra en Tid som så:

$config[zx-auto] not found$config[zx-overlay] not found