Introduktion
Når du bruger MongoDB, har du mulighed for at være fleksibel med strukturen af dine data. Du er ikke låst til at opretholde et bestemt skema, som alle dine dokumenter skal passe ind i. For ethvert givet felt i et dokument kan du bruge enhver af de tilgængelige datatyper understøttet af MongoDB. På trods af denne standard måde at arbejde på, er du i stand til at pålægge et JSON-skema i MongoDB for at tilføje validering på dine samlinger, hvis det ønskes. Vi vil ikke gå i detaljer med skemadesign i denne vejledning, men det kan have en effekt på dataindtastning, hvis det implementeres.
Datatyper angiver et generelt mønster for de data, de accepterer og gemmer. Det er altafgørende at forstå, hvornår man skal vælge en bestemt datatype frem for en anden, når man planlægger sin database. Den valgte type kommer til at diktere, hvordan du kan betjene dine data, og hvordan de opbevares.
JSON og BSON
Før du går ind i detaljerne for specifikke datatyper, er det vigtigt at have en forståelse af, hvordan MongoDB gemmer data. MongoDB og mange andre dokumentbaserede NoSQL-databaser bruger JSON (JavaScript Object Notation) til at repræsentere dataposter som dokumenter.
Der er mange fordele ved at bruge JSON til at gemme data. Nogle af dem er:
- let at læse, lære og dets fortrolighed blandt udviklere
- fleksibilitet i formatet, uanset om det er sparsomt, hierarkisk eller dybt indlejret
- selv-beskrivende, som gør det muligt for applikationer nemt at arbejde med JSON-data
- tillader fokus på et minimalt antal grundlæggende typer
JSON understøtter alle de grundlæggende datatyper som streng, tal, boolean osv. MongoDB gemmer faktisk dataposter som binært kodede JSON (BSON) dokumenter. Ligesom JSON understøtter BSON indlejring af dokumenter og arrays i andre dokumenter og arrays. BSON giver mulighed for yderligere datatyper, der ikke er tilgængelige for JSON.
Hvad er datatyperne i MongoDB?
Før vi går i detaljer, lad os tage et bredt overblik over, hvilke datatyper der understøttes i MongoDB.
MongoDB understøtter en række datatyper, der egner sig til forskellige typer af både simple og komplekse data. Disse omfatter:
Tekst
String
Numerisk
32-Bit Integer
64-Bit Integer
Double
Decimal128
Dato/klokkeslæt
Date
Timestamp
Andet
Object
Array
Binary Data
ObjectId
Boolean
Null
Regular Expression
JavaScript
Min Key
Max Key
I MongoDB har hver BSON-type både et heltal og strengidentifikatorer. Vi vil dække de mest almindelige af disse mere i dybden i denne vejledning.
Strengtyper
Strengtypen er den mest almindeligt anvendte MongoDB-datatype. Enhver værdi skrevet inde i dobbelte anførselstegn ""
i JSON er en strengværdi. Enhver værdi, som du ønsker skal gemmes som tekst, vil bedst blive skrevet som en String
. BSON-strenge er UTF-8 og er repræsenteret i MongoDB som:
Type | Number | Alias | ------------------ | ------ | -------- | String | 2 | "string" |
Generelt vil drivere til programmeringssprog konvertere fra sprogets strengformat til UTF-8 ved serialisering og deserialisering af BSON. Dette gør BSON til en attraktiv metode til f.eks. nem opbevaring af internationale karakterer.
Indsættelse af et dokument med en String
datatypen vil se nogenlunde sådan ud:
db.mytestcoll.insertOne({first_name: "Alex"}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d15")}
Forespørgsel i samlingen vil returnere følgende:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex"}
Brug af $type
operatør
Før du går videre til vores næste datatype, er det vigtigt at vide, hvordan du kan skrive, kontrollere værdien, før du foretager indsættelser. Vi vil bruge det forrige eksempel til at demonstrere brugen af $type
operatør i MongoDB.
Lad os sige, at det er et stykke tid siden, vi arbejdede med mytestcoll
samling fra før. Vi ønsker at indsætte nogle yderligere dokumenter i samlingen med first_name
Mark. For at kontrollere, at vi brugte String
som datatypen gemt som værdien first_name
oprindeligt kan vi køre følgende ved at bruge enten alias- eller talværdien af datatypen:
db.mytestcoll.find( { "first_name": { $type: "string" } } )
Eller
db.mytestcoll.find( { "first_name": { $type: 2 } } )
Begge forespørgsler returnerer et output af alle dokumenter, der har en String
værdi gemt for first_name
fra vores forrige afsnits indsættelse:
[ { _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex" } ]
Hvis du forespørger efter en type, der ikke er gemt i first_name
i ethvert dokument, får du intet resultat. Dette indikerer, at det er en anden datatype, der er gemt i first_name
.
Du er også i stand til at forespørge efter flere datatyper ad gangen med $type
operatør som følgende:
db.mytestcoll.find( { "first_name": { $type: ["string", "null"] } } )
Fordi vi ikke har indsat nogen Null
indtaste værdier i vores samling, vil resultatet være det samme:
[ { _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex" } ]
Du kan bruge den samme metode med alle de følgende typer, som vi vil diskutere.
Tal og numeriske værdier
MongoDB inkluderer en række numeriske datatyper, der egner sig til forskellige scenarier. Beslutningen om, hvilken type der skal bruges, afhænger af arten af de værdier, du planlægger at gemme, og dine use cases for dataene. JSON kalder alt med numre for et Nummer . Det tvinger systemet til at finde ud af, hvordan det omdannes til den nærmeste indbyggede datatype. Vi starter med at udforske heltal, og hvordan de fungerer i MongoDB.
Heltal
Integer
datatype bruges til at gemme tal som hele tal uden brøker eller decimaler. Heltal kan enten være positive eller negative værdier. Der er to typer i MongoDB, 32-Bit Integer
og 64-Bit Integer
. De kan repræsenteres på de to måder, der er vist i tabellen nedenfor, number
og alias
:
Integer type | number | alias | ------------ | ----- | ------------ | `32-bit integer`| 16 | "int" | `64-bit integer`| 18 | "long" |
De områder, en værdi kan passe ind i for hver type, er følgende:
Integer type | Applicable signed range | Applicable unsigned range | ------------ | ------------------------------ | ------------------------------- | `32-bit integer`| -2,147,483,648 to 2,147,483,647| 0 to 4,294,967,295 | `64-bit integer`| -9,223,372,036,854,775,808 to | 0 to 18,446,744,073,709,551,615 9,223,372,036,854,775,807
Ovenstående typer er begrænset af deres gyldige rækkevidde. Enhver værdi uden for området vil resultere i en fejl. Indsættelse af et Integer
indtastning i MongoDB vil se ud som nedenstående:
db.mytestcoll.insertOne({age: 26}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d14")}
Og at finde resultatet vil returnere følgende:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d14"), age: 26}
Som foreslået af navnene, et 32-Bit Integer
har 32 bit heltalspræcision, hvilket er nyttigt til mindre heltalsværdier, som du ikke ønsker at gemme som en sekvens af cifre. Når du vokser i talstørrelse, er du i stand til at støde op til 64-Bit Integer
som har 64 bit heltalspræcision og passer til samme use case som førstnævnte.
Dobbelt
I BSON er standarderstatningen for JSONs nummer er Double
datatype. Double
datatypen bruges til at gemme en flydende kommaværdi og kan repræsenteres i MongoDB sådan:
Type | Number | Alias | ------------------ | ------ | -------- | Double | 1 | "double" |
Flydende kommatal er en anden måde at udtrykke decimaltal på, men uden nøjagtig, konsekvent præcision.
Flydende kommatal kan arbejde med et stort antal decimaler effektivt, men ikke altid nøjagtigt. Det følgende er et eksempel på indtastning af et dokument med Double
skriv i din samling:
db.mytestcoll.insertOne({testScore: 89.6}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d13")}
Der kan være små forskelle mellem input og output, når der beregnes med doubler, hvilket potentielt kan føre til uventet adfærd. Når du udfører operationer, der kræver nøjagtige værdier, har MongoDB en mere præcis type.
Decimal128
Hvis du arbejder med meget store tal med masser af flydende decimalområde, er Decimal128
BSON datatype vil være den bedste mulighed. Dette vil være den mest nyttige type for værdier, der kræver meget præcision, som i brugssager, der involverer nøjagtige monetære operationer. Decimal128
type er repræsenteret som:
Type | Number | Alias | ------------------ | ------ | --------- | Decimal128 | 19 | "decimal" |
BSON-typen, Decimal128
, giver 128 bits decimalrepræsentation til lagring af tal, hvor præcis afrunding af decimaler er vigtig. Decimal128
understøtter 34 decimalcifre med præcision eller en sinificand med et interval på -6143 til +6144. Dette giver mulighed for en høj grad af præcision.
Indsættelse af en værdi ved hjælp af Decimal128
datatypen kræver brug af NumberDecimal()
konstruktør med dit nummer som en String
for at forhindre MongoDB i at bruge den numeriske standardtype, Double
.
Her demonstrerer vi dette:
db.mytestcoll.insertOne({price : NumberDecimal("5.099")}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d12")}
Når du forespørger samlingen, får du så følgende retur:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d12"), price: "5.099" }
Den numeriske værdi bevarer sin præcision, hvilket muliggør nøjagtige operationer. For at demonstrere Decimal128
type versus Double
, kan vi gennemgå følgende øvelse.
Hvordan præcision kan gå tabt baseret på datatype
Lad os sige, at vi vil indsætte et tal med mange decimaler som en Double
ind i MongoDB med følgende:
db.mytestcoll.insertOne({ price: 9999999.4999999999 }){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d24")}
Når vi forespørger efter disse data, får vi følgende resultat:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d24"), price: 9999999.5}
Denne værdi runder op til 9999999.5
mister den nøjagtige værdi, som vi indtastede den med. Dette gør Double
dårligt egnet til lagring af tal med mange decimaler.
Det næste eksempel viser, hvor præcision vil gå tabt, når du sender en Double
implicit med Decimal128
i stedet for en String
ligesom i det foregående eksempel.
Vi starter med at indsætte følgende Double
igen, men med NumberDecimal()
for at gøre det til en Decimal128
type:
db.mytestcoll.insertOne({ price: NumberDecimal( 9999999.4999999999 ) }){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d14")}
Bemærk :Når du foretager denne indsættelse i MongoDB-skallen, vises følgende advarselsmeddelelse:
Warning: NumberDecimal: specifying a number as argument is deprecated and may lead to loss of precision, pass a string instead
Denne advarselsmeddelelse angiver, at det nummer, du forsøger at passere, kan være genstand for tab af præcision. De foreslår at bruge en String
ved hjælp af NumberDecimal()
så du ikke mister nogen præcision.
Hvis vi ignorerer advarslen og indsætter dokumentet alligevel, ses tabet af præcision i forespørgselsresultaterne fra afrundingen af værdien:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d14"), price: Decimal128("9999999.50000000")}
Hvis vi følger den anbefalede NumberDecimal()
tilgang ved hjælp af en String
vi vil se følgende resultater med bevaret præcision:
db.mytestcoll.insertOne({ price: NumberDecimal( "9999999.4999999999" ) } )
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d14"), price: Decimal128("9999999.4999999999")}
For enhver brug, der kræver præcise, nøjagtige værdier, kan denne returnering forårsage problemer. Ethvert arbejde, der involverer monetære operationer, er et eksempel, hvor præcision vil være ekstremt vigtig, og at have nøjagtige værdier er afgørende for nøjagtige beregninger. Denne demonstration fremhæver vigtigheden af at vide, hvilken numerisk datatype der vil være bedst egnet til dine data.
Dato
BSON Date
datatypen er et 64-bit heltal, der repræsenterer antallet af millisekunder siden Unix-epoken (1. januar 1970). Denne datatype gemmer den aktuelle dato eller tid og kan returneres som enten et datoobjekt eller som en streng. Date
er repræsenteret i MongoDB som følger:
Type | Number | Alias | ------------------ | ------ | ------------ | Date | 9 | "date" |
Bemærk :BSON Date
type er underskrevet. Negative værdier repræsenterer datoer før 1970.
Der er tre metoder til at returnere datoværdier.
-
Date()
- returnerer en streng -
new Date()
- returnerer et datoobjekt ved hjælp afISODate()
indpakning -
ISODate()
- returnerer også et datoobjekt ved hjælp afISODate()
indpakning
Vi viser disse muligheder nedenfor:
var date1 = Date()var date2 = new Date()var date3 = ISODate()db.mytestcoll.insertOne({firstDate: date1, secondDate: date2, thirdDate: date3}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d22")}
Og ved returnering:
db.mytestcoll.find().pretty(){ "_id" : ObjectId("614b37296a124db40ae74d22"), firstDate: 'Tue Sep 28 2021 11:28:52 GMT+0200 (Central European Summer Time)', secondDate: ISODate("2021-09-28T09:29:01.924Z"), thirdDate: ISODate("2021-09-28T09:29:12.151Z")}
Tidsstempel
Der er også Timestamp
datatype i MongoDB til at repræsentere tid. Dog Timestamp
vil være mest nyttig til intern brug og er ikke knyttet til Date
type. Selve typen er en sekvens af tegn, der bruges til at beskrive datoen og klokkeslættet, hvor en begivenhed indtræffer. Timestamp
er en 64 bit værdi hvor:
- de mest signifikante 32 bit er
time_t
værdi (sekunder siden Unix-epoken) - de mindst signifikante 32 bit er en stigende
ordinal
for operationer inden for et givet sekund
Dens repræsentation i MongoDB vil se ud som følger:
Type | Number | Alias | ------------------ | ------ | ------------ | Timestamp | 17 | "timestamp" |
Når du indsætter et dokument, der indeholder felter på øverste niveau med tomme tidsstempler, vil MongoDB erstatte den tomme tidsstempelværdi med den aktuelle tidsstempelværdi. Undtagelsen til dette er, hvis _id
feltet indeholder et tomt tidsstempel. Tidsstempelværdien vil altid blive indsat som den er og ikke erstattet.
Indsættelse af et nyt Timestamp
værdi i MongoDB vil bruge new Timestamp()
funktion og ser sådan ud:
db.mytestcoll.insertOne( {ts: new Timestamp() });{ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d23")}
Når du forespørger samlingen, returnerer du et resultat, der ligner:
db.mytestcoll.find().pretty(){ "_id" : ObjectId("614b37296a124db40ae74d24"), "ts" : Timestamp( { t: 1412180887, i: 1 })}
Objekt
Object
datatype i MongoDB bruges til lagring af indlejrede dokumenter. Et indlejret dokument er en række indlejrede dokumenter i key: value
parformat. Vi demonstrerer Object
skriv nedenfor:
var classGrades = {"Physics": 88, "German": 92, "LitTheoery": 79}db.mytestcoll.insertOne({student_name: "John Smith", report_card: classGrades}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d18")}
Vi kan derefter se vores nye dokument:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d18"), student_name: 'John Smith', report_card: {Physics: 88, German: 92, LitTheoery: 79}}
Object
datatype optimerer til lagring af data, der bedst tilgås sammen. Det giver nogle effektiviteter omkring opbevaring, hastighed og holdbarhed i modsætning til at gemme hvert klassemærke fra ovenstående eksempel separat.
Binære data
Binary Data
, eller BinData
, gør datatypen præcis, hvad dens navn antyder, og gemmer binære data for et felts værdi. BinData
bruges bedst, når du gemmer og søger efter data, på grund af dets effektivitet til at repræsentere bit-arrays. Denne datatype kan repræsenteres på følgende måder:
Type | Number | Alias | ------------------ | ------ | ------------ | Binary data | 5 | "binData" |
Her er et eksempel på tilføjelse af nogle Binary data
ind i et dokument i en samling:
var data = BinData(1, "111010110111100110100010101")db.mytestcoll.insertOne({binaryData: data}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d20")}
For derefter at se det resulterende dokument:
db.mytestcoll.find().pretty(){ "_id" : ObjectId("614b37296a124db40ae74d20"), "binaryData" : BinData(1, "111010110111100110100010101")}
ObjectId
ObjectId
type er specifik for MongoDB, og den gemmer dokumentets unikke ID. MongoDB giver en _id
felt for hvert dokument. ObjectId er 12 bytes i størrelse og kan repræsenteres som følger:
Type | Number | Alias | ------------------ | ------ | ------------ | ObjectId | 7 | "objectId" |
ObjectId består af tre dele, der udgør dens 12-byte makeup:
- en 4-byte tidsstempelværdi , der repræsenterer objekt-id'ets skabelse, målt i sekunder siden Unix-epoken
- en 5-byte tilfældig værdi
- en 3-byte stigende tæller initialiseret til en tilfældig værdi
I MongoDB kræver hvert dokument i en samling et unikt _id
at fungere som en primær nøgle. Hvis _id
feltet efterlades tomt for et indsat dokument, vil MongoDB automatisk generere et ObjectId for feltet.
Der er flere fordele ved at bruge ObjectIds til _id
:
- på
mongosh
(MongoDB shell), oprettelsestidspunktet forObjectId
er tilgængelig ved hjælp afObjectId.getTimestamp()
metode. - sortering på et
_id
felt, der gemmerObjectId
datatyper svarer tæt til sortering efter oprettelsestidspunkt.
Vi har set ObjectId'er gennem eksemplerne indtil videre, og de vil ligne dette:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d19")}
Bemærk :ObjectId-værdier bør stige over tid, men de er ikke nødvendigvis monotone. Dette er fordi de:
- Indeholder kun et sekunds tidsmæssig opløsning, så værdier oprettet inden for samme sekund har ikke garanteret rækkefølge
- værdier genereres af klienter, som kan have forskellige systemure
Boolean
MongoDB har den oprindelige Boolean
datatype til lagring af sande og falske værdier i en samling. Boolean
i MongoDB kan repræsenteres som følger:
Type | Number | Alias | ------------------ | ------ | ------------ | Boolean | 8 | "bool" |
Indsættelse af et dokument med en Boolean
datatypen vil se nogenlunde sådan ud:
db.mytestcoll.insertOne({isCorrect: true, isIncorrect: false}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d21")}
Når du derefter søger efter dokumentet, vil resultatet blive vist som:
db.mytestcoll.find().pretty(){ "_id" : ObjectId("614b37296a124db40ae74d21") "isCorrect" : true, "isIncorrect" : false}
Regulært udtryk
Regular Expression
datatype i MongoDB giver mulighed for lagring af regulære udtryk som værdien af et felt. MongoDB bruger PCRE (Perl Compatible Regular Expression) som sit regulære udtrykssprog.
Den kan repræsenteres på følgende måde:
Type | Number | Alias | ------------------ | ------ | ------- | Regular Expression | 11 | "regex" |
BSON giver dig mulighed for at undgå det typiske "konverter fra streng"-trin, som er almindeligt forekommende, når du arbejder med regulære udtryk og databaser. Denne type vil være mest nyttig, når du skriver databaseobjekter, der kræver valideringsmønstre eller matchende triggere.
For eksempel kan du indsætte Regular Expression
datatype som denne:
db.mytestcoll.insertOne({exampleregex: /tt/}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d16")}db.mytestcoll.insertOne({exampleregext:/t+/}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d17")}
Denne sekvens af udsagn vil tilføje disse dokumenter til din samling. Du kan derefter forespørge i din samling for at finde de indsatte dokumenter:
db.mytestcoll.find().pretty(){ _id: ObjectId("614b37296a124db40ae74d16"), exampleregex: /tt/, _id: ObjectId("614b37296a124db40ae74d17"), exampleregex: /t+/ }
De regulære udtryksmønstre gemmes som regex og ikke som strenge. Dette giver dig mulighed for at forespørge efter en bestemt streng og få returnerede dokumenter, der har et regulært udtryk, der matcher den ønskede streng.
JavaScript (uden omfang)
Meget ligesom det tidligere nævnte Regular Expression
datatype, giver BSON MongoDB mulighed for at gemme JavaScript-funktioner uden omfang som deres egen type. JavaScript
type kan genkendes som følger:
Type | Number | Alias | ------------------ | ------ | ------------ | JavaScript | 13 | "javascript" |
Tilføjelse af et dokument til din samling med JavaScript
datatypen vil se nogenlunde sådan ud:
db.mytestcoll.insertOne({jsCode: "function(){var x; x=1}"}){ "acknowledged": true, "insertedId": ObjectId("614b37296a124db40ae74d122")}
Denne funktionalitet giver dig mulighed for at gemme JavaScript-funktioner inde i dine MongoDB-samlinger, hvis det er nødvendigt til en bestemt brug.
Bemærk :Med MongoDB version 4.4 og nyere, en alternativ JavaScript-type, JavaScript with Scope
datatype, er blevet forældet
Konklusion
I denne artikel har vi dækket de fleste af de almindelige datatyper, der er nyttige, når du arbejder med MongoDB-databaser. Der er yderligere typer, som ikke er eksplicit dækket i denne vejledning, som kan være nyttige afhængigt af brugssituationen. At komme i gang ved at kende disse typer dækker de fleste brugssager. Det er et stærkt grundlag for at begynde at modellere din MongoDB-database.
Det er vigtigt at vide, hvilke datatyper der er tilgængelige for dig, når du bruger en database, så du bruger gyldige værdier og arbejder på dataene med forventede resultater. Der er risici, du kan løbe ind i uden at indtaste dine data korrekt, som vist i Double
versus Decimal128
dyrke motion. Det er vigtigt at tænke over dette, før du forpligter dig til en given type.
Hvis du er interesseret i at tjekke Prisma ud med en MongoDB-database, kan du tjekke dataforbindelsesdokumentationen.