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

Introduktion til MongoDB datatyper


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.

  1. Date() - returnerer en streng

  2. new Date() - returnerer et datoobjekt ved hjælp af ISODate() indpakning

  3. ISODate() - returnerer også et datoobjekt ved hjælp af ISODate() 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 :

  • mongosh (MongoDB shell), oprettelsestidspunktet for ObjectId er tilgængelig ved hjælp af ObjectId.getTimestamp() metode.
  • sortering på et _id felt, der gemmer ObjectId 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.




  1. Import af Dato-datatype ved hjælp af mongoimport

  2. Hvad er fordelen ved at bruge Gorilla-sessions tilpasset backend?

  3. Migrering af socket.io fra 0.9.x til 1.x, problemer med at konfigurere RedisStore

  4. Til hvilket niveau låser MongoDB skrivning? (eller:hvad betyder det med per forbindelse