1. Oversigt
Nogle gange har vi brug for ID'et på et dokument, vi lige har indsat i en MongoDB-database. For eksempel vil vi måske sende ID'et tilbage som et svar til en opkalder eller logge det oprettede objekt til fejlretning.
I denne vejledning vil vi se, hvordan ID'er implementeres i MongoDB, og hvordan man henter ID'et for et dokument, vi lige har indsat i en samling via et Java-program.
2. Hvad er ID'et for et MongoDB-dokument?
Som i ethvert datalagringssystem har MongoDB brug for en unik identifikator for hvert dokument, der er gemt i en samling. Denne identifikator svarer til den primære nøgle i relationelle databaser.
I MongoDB er dette ID sammensat af 12 bytes:
- en 4-byte tidsstempelværdi repræsenterer sekunderne siden Unix-epoken
- en 5-byte tilfældig værdi genereret én gang pr. proces. Denne tilfældige værdi er unik for maskinen og processen.
- en 3-byte stigende tæller
ID'et er gemt i et felt med navnet _id og genereres af klienten. Det betyder, at ID'et skal genereres, før dokumentet sendes til databasen. På klientsiden kan vi enten bruge et drivergenereret ID eller generere et brugerdefineret ID.
Vi kan se, at dokumenter oprettet af den samme klient i samme sekund vil have de første 9 bytes til fælles. Derfor er det unikke ved ID'et afhængig af tælleren i dette tilfælde. Tælleren lader en klient oprette over 16 millioner dokumenter på samme sekund.
Selvom det starter med et tidsstempel, skal vi være forsigtige med, at identifikatoren ikke bruges som et sorteringskriterium. Dette skyldes, at dokumenter, der er oprettet i samme sekund, ikke garanteres at blive sorteret efter oprettelsesdato, da tælleren ikke garanteres at være monoton. Forskellige klienter kan også have forskellige systemure.
Java-driveren bruger en tilfældig talgenerator til tælleren, som ikke er monotonisk. Derfor bør vi ikke bruge det drivergenererede ID til at sortere efter oprettelsesdato.
3. ObjectId Klasse
Den unikke identifikator er gemt i et ObjectId klasse, som giver praktiske metoder til at få data gemt i ID'et uden at parse det manuelt.
For eksempel, her er, hvordan vi kan få oprettelsesdatoen for id'et:
Date creationDate = objectId.getDate();
Ligeledes kan vi hente tidsstemplet for ID'et på få sekunder :
int timestamp = objectId.getTimestamp();
ObjectId klasse giver også metoder til at hente tælleren, maskin-id'en eller proces-id'en, men de er alle forældede.
4. Henter ID'et
Den vigtigste ting at huske er, at i MongoDB genererer klienten den unikke identifikator for et Dokument før den sendes til klyngen. Dette er i modsætning til sekvenser i relationelle databaser. Dette gør det ret nemt at hente dette ID.
4.1. Driver-genereret ID
Den standard og nemme måde at generere det unikke ID for et Dokument er ved at lade chaufføren gøre arbejdet. Når vi indsætter et nyt Dokument til en samling , hvis ikke _id feltet findes i Dokumentet , genererer driveren et nyt ObjectId før du sender insert-kommandoen til klyngen.
Vores kode til at indsætte et nyt Dokument ind i din samling kan se sådan ud :
Document document = new Document();
document.put("name", "Shubham");
document.put("company", "Baeldung");
collection.insertOne(document);
Vi kan se, at vi aldrig angiver, hvordan ID'et skal genereres.
Når insertOne() metoden returnerer, kan vi få det genererede ObjectId fra Dokumentet :
ObjectId objectId = document.getObjectId("_id");
Vi kan også hente ObjectId som et standardfelt i Dokumentet og cast den derefter til ObjectId :
ObjectId oId = (ObjectId) document.get("_id");
4.2. Brugerdefineret ID
Den anden måde at hente ID'et på er at generere det i vores kode og indsætte det i Dokumentet som ethvert andet felt. Hvis vi sender et Dokument med et _id felt til driveren, vil det ikke generere et nyt.
Vi kan kræve dette i nogle tilfælde, hvor vi har brug for ID'et for MongoDB Dokumentet før du indsætter Dokumentet i Samlingen .
Vi kan generere et nyt ObjectId ved at oprette en ny forekomst af klassen :
ObjectId generatedId = new ObjectId();
Eller vi kan også kalde den statiske get() metoden for ObjectId klasse:
ObjectId generatedId = ObjectId.get();
Så skal vi bare oprette vores Dokument og brug det genererede ID. For at gøre det kan vi give det i Dokumentet konstruktør:
Document document = new Document("_id", generatedId);
Alternativt kan vi bruge put() metode:
document.put("_id", generatedId);
Når vi bruger et brugergenereret ID, skal vi være forsigtige med at generere et nyt ObjectId før hver indsættelse, da duplikerede ID'er er forbudt. Dublerede ID'er vil resultere i en MongoWriteException med en dublet nøglemeddelelse.
ObjectId klasse giver flere andre konstruktører, som giver os mulighed for at indstille nogle dele af identifikatoren:
public ObjectId(final Date date)
public ObjectId(final Date date, final int counter)
public ObjectId(final int timestamp, final int counter)
public ObjectId(final String hexString)
public ObjectId(final byte[] bytes)
public ObjectId(final ByteBuffer buffer)
Men vi bør være meget forsigtige, når vi bruger disse konstruktører, da det unikke ved det ID, der leveres til driveren, udelukkende afhænger af vores kode. Vi kan få duplikatnøglefejl i disse særlige tilfælde:
- hvis vi bruger den samme dato (eller tidsstempel) og tællerkombination flere gange
- Hvis vi bruger den samme hexadecimale streng , byte array eller ByteBuffer flere gange