sql >> Databasteknik >  >> NoSQL >> MongoDB

Introduktion till MongoDB-datatyper


Introduktion

När du använder MongoDB har du möjlighet att vara flexibel med strukturen på dina data. Du är inte låst till att upprätthålla ett visst schema som alla dina dokument måste passa in i. För varje givet fält i ett dokument kan du använda vilken som helst av de tillgängliga datatyperna stöds av MongoDB. Trots detta standardsätt att arbeta kan du införa ett JSON-schema i MongoDB för att lägga till validering på dina samlingar om så önskas. Vi går inte in på detaljerna om schemadesign i den här guiden, men det kan ha en effekt på datainmatning om det implementeras.

Datatyper anger ett allmänt mönster för den data de accepterar och lagrar. Det är ytterst viktigt att förstå när man ska välja en viss datatyp framför en annan när man planerar sin databas. Den valda typen kommer att diktera hur du kan hantera din data och hur den lagras.



JSON och BSON

Innan du går in på detaljerna för specifika datatyper är det viktigt att ha en förståelse för hur MongoDB lagrar data. MongoDB och många andra dokumentbaserade NoSQL-databaser använder JSON (JavaScript Object Notation) för att representera dataposter som dokument.

Det finns många fördelar med att använda JSON för att lagra data. Några av dem är:

  • lätthet att läsa, lära sig och dess förtrogenhet bland utvecklare
  • flexibilitet i format, oavsett om det är gles, hierarkiskt eller djupt kapslat
  • självbeskrivande, vilket gör att applikationer enkelt kan arbeta med JSON-data
  • gör det möjligt att fokusera på ett minimalt antal grundläggande typer

JSON stöder alla grundläggande datatyper som sträng, nummer, boolean, etc. MongoDB lagrar faktiskt dataposter som binärkodade JSON-dokument (BSON). Precis som JSON stöder BSON inbäddning av dokument och arrayer i andra dokument och arrayer. BSON tillåter ytterligare datatyper som inte är tillgängliga för JSON.



Vilka är datatyperna i MongoDB?

Innan vi går in i detalj, låt oss ta en bred bild av vilka datatyper som stöds i MongoDB.

MongoDB stöder en rad datatyper som lämpar sig för olika typer av både enkla och komplexa data. Dessa inkluderar:

Sms:a

  • String

Numerisk

  • 32-Bit Integer
  • 64-Bit Integer
  • Double
  • Decimal128

Datum/tid

  • Date
  • Timestamp

Annat

  • Object
  • Array
  • Binary Data
  • ObjectId
  • Boolean
  • Null
  • Regular Expression
  • JavaScript
  • Min Key
  • Max Key

I MongoDB har varje BSON-typ både ett heltal och strängidentifierare. Vi kommer att täcka de vanligaste av dessa mer ingående i den här guiden.



Strängtyper

Strängtypen är den mest använda MongoDB-datatypen. Alla värden skrivna inuti dubbla citattecken "" i JSON är ett strängvärde. Alla värden som du vill ska lagras som text skrivs bäst som en String . BSON-strängar är UTF-8 och representeras i MongoDB som:

        Type         | Number |  Alias   |  ------------------ | ------ | -------- |       String        |    2   | "string" |

Generellt kommer drivrutiner för programmeringsspråk att konvertera från språkets strängformat till UTF-8 vid serialisering och avserialisering av BSON. Detta gör BSON till en attraktiv metod för att till exempel enkelt lagra internationella tecken.

Infoga ett dokument med en String datatypen kommer att se ut ungefär så här:

db.mytestcoll.insertOne({first_name: "Alex"}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d15")}

Om du frågar efter samlingen returneras följande:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d15"),         first_name: "Alex"}

Använda $type operatör

Innan du går vidare till vår nästa datatyp är det viktigt att veta hur du kan skriva kontrollera värdet innan du gör några infogar. Vi kommer att använda föregående exempel för att demonstrera hur vi använder $type operatör i MongoDB.

Låt oss säga att det har gått ett tag sedan vi arbetade med mytestcoll samling från tidigare. Vi vill infoga några ytterligare dokument i samlingen med first_name fält. För att kontrollera att vi använde String som datatypen lagrad som ett värde på first_name ursprungligen kan vi köra följande med antingen alias- eller nummervärdet för datatypen:

db.mytestcoll.find( { "first_name": { $type: "string" } } )

Eller

db.mytestcoll.find( { "first_name": { $type: 2 } } )

Båda frågorna returnerar en utdata av alla dokument som har en String värde lagrat för first_name från vårt tidigare avsnitts infogning:

[ { _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex" } ]

Om du frågar efter en typ som inte är lagrad i first_name fältet i något dokument får du inget resultat. Detta indikerar att det är en annan datatyp som lagras i first_name .

Du kan också fråga efter flera datatyper samtidigt med $type operatör som följande:

db.mytestcoll.find( { "first_name": { $type: ["string", "null"] } } )

Eftersom vi inte infogade någon Null skriv in värden i vår samling, resultatet blir detsamma:

[ { _id: ObjectId("614b37296a124db40ae74d15"), first_name: "Alex" } ]

Du kan använda samma metod med alla följande typer som vi kommer att diskutera.




Siffror och numeriska värden

MongoDB innehåller en rad numeriska datatyper som är lämpliga för olika scenarier. Att bestämma vilken typ som ska användas beror på arten av de värden du planerar att lagra och dina användningsfall för data. JSON kallar allt med nummer ett Nummer . Det tvingar systemet att ta reda på hur det ska omvandlas till närmaste inbyggda datatyp. Vi börjar med att utforska heltal och hur de fungerar i MongoDB.


Heltal

Integer datatyp används för att lagra tal som heltal utan bråktal eller decimaler. Heltal kan antingen vara positiva eller negativa värden. Det finns två typer i MongoDB, 32-Bit Integer och 64-Bit Integer . De kan representeras på de två sätt som visas i tabellen nedan, number och alias :

  Integer type   | number |    alias     |   ------------   | -----  | ------------ |  `32-bit integer`|   16   |    "int"     | `64-bit integer`|   18   |    "long"    |

De intervall som ett värde kan passa in i för varje typ är följande:

  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

Typerna ovan är begränsade av deras giltiga intervall. Alla värden utanför intervallet kommer att resultera i ett fel. Infoga ett Integer skriv in MongoDB kommer att se ut som nedan:

db.mytestcoll.insertOne({age: 26}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d14")}

Och att hitta resultatet kommer att returnera följande:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d14"), age: 26}

Som föreslagits av namnen, ett 32-Bit Integer har 32 bitars heltalsprecision vilket är användbart för mindre heltalsvärden som du inte vill lagra som en sekvens av siffror. När du växer i antalsstorlek kan du komma upp till 64-Bit Integer som har 64 bitars heltalsprecision och passar samma användningsfall som den förra.



Dubbel

I BSON är standardersättningen för JSONs nummer är Double data typ. Double datatyp används för att lagra ett flyttalsvärde och kan representeras i MongoDB så här:

        Type         | Number |   Alias  |  ------------------ | ------ | -------- |       Double        |    1   | "double" |

Flyttal är ett annat sätt att uttrycka decimaltal, men utan exakt, konsekvent precision.

Flyttal kan fungera med ett stort antal decimaler effektivt men inte alltid exakt. Följande är ett exempel på hur du skriver in ett dokument med Double skriv i din samling:

db.mytestcoll.insertOne({testScore: 89.6}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d13")}

Det kan finnas små skillnader mellan input och output vid beräkning med dubblar som potentiellt kan leda till oväntat beteende. När man utför operationer som kräver exakta värden har MongoDB en mer exakt typ.



Decimal128

Om du arbetar med mycket stora siffror med många flyttalsintervall, är Decimal128 BSON-datatyp kommer att vara det bästa alternativet. Detta kommer att vara den mest användbara typen för värden som kräver mycket precision som i användningsfall som involverar exakta monetära operationer. Decimal128 typ representeras som:

        Type         | Number |   Alias   |  ------------------ | ------ | --------- |      Decimal128     |   19   | "decimal" |

BSON-typen, Decimal128 , ger 128 bitars decimalrepresentation för lagring av tal där det är viktigt att avrunda decimaler exakt. Decimal128 stöder 34 decimalsiffror med precision, eller en sinificand med ett intervall på -6143 till +6144. Detta möjliggör en hög precision.

Infoga ett värde med Decimal128 datatypen kräver att NumberDecimal() används konstruktor med ditt nummer som en String för att hindra MongoDB från att använda standardnumerisk typ, Double .

Här visar vi detta:

db.mytestcoll.insertOne({price : NumberDecimal("5.099")}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d12")}

När du frågar efter samlingen får du följande retur:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d12"),         price: "5.099" }

Det numeriska värdet bibehåller sin precision vilket möjliggör exakta operationer. För att demonstrera Decimal128 typ kontra Double , vi kan gå igenom följande övning.



Hur precision kan förloras baserat på datatyp

Säg att vi vill infoga ett tal med många decimaler som en Double till MongoDB med följande:

db.mytestcoll.insertOne({ price: 9999999.4999999999 }){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d24")}

När vi frågar efter denna data får vi följande resultat:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d24"),         price: 9999999.5}

Detta värde avrundas uppåt till 9999999.5 , förlorar sitt exakta värde som vi matade in det med. Detta gör Double dåligt lämpad för lagring av tal med många decimaler.

Nästa exempel visar var precision går förlorad när du skickar en Double implicit med Decimal128 istället för en String som i föregående exempel.

Vi börjar med att infoga följande Double igen men med NumberDecimal() för att göra det till en Decimal128 typ:

db.mytestcoll.insertOne({ price: NumberDecimal( 9999999.4999999999 ) }){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d14")}

Obs :När du gör denna infogning i MongoDB-skalet, visas följande varningsmeddelande:

Warning: NumberDecimal: specifying a number as argument is deprecated and may lead to loss of precision, pass a string instead

Detta varningsmeddelande indikerar att numret du försöker passera kan vara föremål för en förlust av precision. De föreslår att du använder en String med NumberDecimal() så att du inte tappar precisionen.

Om vi ​​ignorerar varningen och sätter in dokumentet ändå, ses förlusten av precision i sökresultatet från avrundningen uppåt av värdet:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d14"),         price: Decimal128("9999999.50000000")}

Om vi ​​följer den rekommenderade NumberDecimal() tillvägagångssätt med en String vi kommer att se följande resultat med bibehållen precision:

db.mytestcoll.insertOne({ price: NumberDecimal( "9999999.4999999999" ) } )
db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d14"),         price: Decimal128("9999999.4999999999")}

För alla användningsfall som kräver exakta, exakta värden kan denna retur orsaka problem. Allt arbete som involverar monetära operationer är ett exempel där precision kommer att vara extremt viktigt och att ha exakta värden är avgörande för korrekta beräkningar. Den här demonstrationen understryker vikten av att veta vilken numerisk datatyp som passar bäst för din data.




Datum

BSON Date datatypen är ett 64-bitars heltal som representerar antalet millisekunder sedan Unix-epoken (1 januari 1970). Denna datatyp lagrar aktuellt datum eller tid och kan returneras som antingen ett datumobjekt eller som en sträng. Date representeras i MongoDB enligt följande:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |        Date         |    9   |     "date"   |

Obs :BSON Date typ är signerad. Negativa värden representerar datum före 1970.

Det finns tre metoder för att returnera datumvärden.

  1. Date() - returnerar en sträng

  2. new Date() - returnerar ett datumobjekt med ISODate() omslag

  3. ISODate() - returnerar också ett datumobjekt med ISODate() omslag

Vi visar dessa alternativ nedan:

var date1 = Date()var date2 = new Date()var date3 = ISODate()db.mytestcoll.insertOne({firstDate: date1, secondDate: date2, thirdDate: date3}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d22")}

Och vid retur:

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")}


Tidsstämpel

Det finns också Timestamp datatyp i MongoDB för att representera tid. Men Timestamp kommer att vara mest användbar för internt bruk och är det inte kopplat till Date typ. Själva typen är en sekvens av tecken som används för att beskriva datum och tid när en händelse inträffar. Timestamp är ett 64-bitars värde där:

  • de viktigaste 32 bitarna är time_t värde (sekunder sedan Unix-epoken)
  • de minst signifikanta 32 bitarna är en inkrementerande ordinal för operationer inom en given sekund

Dess representation i MongoDB kommer att se ut som följer:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      Timestamp      |   17   |  "timestamp" |

När du infogar ett dokument som innehåller fält på toppnivå med tomma tidsstämplar, kommer MongoDB att ersätta det tomma tidsstämpelvärdet med det aktuella tidsstämpelvärdet. Undantaget från detta är om _id fältet innehåller en tom tidsstämpel. Tidsstämpelvärdet kommer alltid att infogas som det är och inte ersättas.

Infogar en ny Timestamp värde i MongoDB kommer att använda new Timestamp() funktion och ser ut ungefär så här:

db.mytestcoll.insertOne( {ts: new Timestamp() });{        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d23")}

När du frågar efter samlingen returnerar du ett resultat som liknar:

db.mytestcoll.find().pretty(){        "_id" : ObjectId("614b37296a124db40ae74d24"),         "ts" : Timestamp( { t: 1412180887, i: 1 })}


Objekt

Object datatyp i MongoDB används för att lagra inbäddade dokument. Ett inbäddat dokument är en serie kapslade dokument i key: value parformat. Vi demonstrerar Object skriv nedan:

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 sedan se vårt nya dokument:

db.mytestcoll.find().pretty(){    _id: ObjectId("614b37296a124db40ae74d18"),    student_name: 'John Smith',    report_card: {Physics: 88, German: 92, LitTheoery: 79}}

Object datatyp optimerar för lagring av data som är bäst åtkomlig tillsammans. Det ger vissa effektiviteter kring lagring, hastighet och hållbarhet i motsats till att lagra varje klassmärke, från exemplet ovan, separat.



Binära data

Binary Data , eller BinData , datatyp gör exakt vad dess namn antyder och lagrar binär data för ett fälts värde. BinData används bäst när du lagrar och söker efter data, på grund av dess effektivitet när det gäller att representera bitmatriser. Denna datatyp kan representeras på följande sätt:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      Binary data    |    5   |   "binData"  |

Här är ett exempel på att lägga till några Binary data till ett dokument i en samling:

var data = BinData(1, "111010110111100110100010101")db.mytestcoll.insertOne({binaryData: data}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d20")}

För att sedan se det resulterande dokumentet:

db.mytestcoll.find().pretty(){        "_id" : ObjectId("614b37296a124db40ae74d20"),        "binaryData" : BinData(1, "111010110111100110100010101")}


ObjectId

ObjectId typen är specifik för MongoDB och den lagrar dokumentets unika ID. MongoDB tillhandahåller ett _id fält för varje dokument. ObjectId är 12 byte stor och kan representeras enligt följande:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      ObjectId       |    7   |   "objectId" |

ObjectId består av tre delar som utgör dess 12-byte makeup:

  • ett 4-byte tidsstämpelvärde , som representerar objekt-ID:s skapelse, mätt i sekunder sedan Unix-epoken
  • ett 5-byte slumpmässigt värde
  • en 3-byte inkrementerande räknare initieras till ett slumpmässigt värde

I MongoDB kräver varje dokument i en samling ett unikt _id att fungera som en primärnyckel. Om _id fältet lämnas tomt för ett infogat dokument, kommer MongoDB automatiskt att generera ett ObjectId för fältet.

Det finns flera fördelar med att använda ObjectIds för _id :

  • mongosh (MongoDB-skal), skapandet av ObjectId är tillgänglig med ObjectId.getTimestamp() metod.
  • sorterar på ett _id fält som lagrar ObjectId datatyper är en nära motsvarighet till sortering efter skapelsetid.

Vi har sett ObjectIds i exemplen hittills, och de kommer att se ut så här:

db.mytestcoll.find().pretty(){         _id: ObjectId("614b37296a124db40ae74d19")}

Obs :ObjectId-värden bör öka med tiden, men de är inte nödvändigtvis monotona. Detta beror på att de:

  • Innehåller endast en sekunds tidsmässig upplösning, så värden skapade inom samma sekund har inte garanterad ordning
  • värden genereras av klienter, som kan ha olika systemklockor


Boolean

MongoDB har den ursprungliga Boolean datatyp för att lagra sanna och falska värden inom en samling. Boolean i MongoDB kan representeras enligt följande:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |       Boolean       |    8   |     "bool"   |

Infoga ett dokument med en Boolean datatypen kommer att se ut ungefär så här:

db.mytestcoll.insertOne({isCorrect: true, isIncorrect: false}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d21")}

När du sedan söker efter dokumentet kommer resultatet att visas som:

db.mytestcoll.find().pretty(){    "_id" : ObjectId("614b37296a124db40ae74d21")    "isCorrect" : true,    "isIncorrect" : false}


Reguljärt uttryck

Regular Expression datatyp i MongoDB tillåter lagring av reguljära uttryck som värdet på ett fält. MongoDB använder PCRE (Perl Compatible Regular Expression) som sitt reguljära uttrycksspråk.

Dess kan representeras på följande sätt:

        Type         | Number |  Alias  |  ------------------ | ------ | ------- |  Regular Expression |   11   | "regex" |

BSON låter dig undvika det typiska "konvertera från sträng"-steget som är vanligt förekommande när du arbetar med reguljära uttryck och databaser. Den här typen kommer att vara mest användbar när du skriver databasobjekt som kräver valideringsmönster eller matchande triggers.

Till exempel kan du infoga Regular Expression datatyp så här:

db.mytestcoll.insertOne({exampleregex: /tt/}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d16")}db.mytestcoll.insertOne({exampleregext:/t+/}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d17")}

Denna sekvens av uttalanden kommer att lägga till dessa dokument till din samling. Du kan sedan fråga din samling för att hitta de infogade dokumenten:

db.mytestcoll.find().pretty(){        _id: ObjectId("614b37296a124db40ae74d16"), exampleregex: /tt/,        _id: ObjectId("614b37296a124db40ae74d17"), exampleregex: /t+/ }

De reguljära uttrycksmönstren lagras som regex och inte som strängar. Detta gör att du kan fråga efter en viss sträng och få returnerade dokument som har ett reguljärt uttryck som matchar den önskade strängen.



JavaScript (utan omfattning)

Ungefär som det tidigare nämnda Regular Expression datatyp, tillåter BSON MongoDB att lagra JavaScript-funktioner utan räckvidd som sin egen typ. JavaScript typ kan kännas igen enligt följande:

        Type         | Number |     Alias    |  ------------------ | ------ | ------------ |      JavaScript     |   13   | "javascript" |

Lägga till ett dokument till din samling med JavaScript datatypen kommer att se ut ungefär så här:

db.mytestcoll.insertOne({jsCode: "function(){var x; x=1}"}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d122")}

Denna funktion låter dig lagra JavaScript-funktioner i dina MongoDB-samlingar om det behövs för ett visst användningsfall.

Obs :Med MongoDB version 4.4 och senare, en alternativ JavaScript-typ, JavaScript with Scope datatyp, har fasats ut



Slutsats

I den här artikeln har vi täckt de flesta vanliga datatyper som är användbara när du arbetar med MongoDB-databaser. Det finns ytterligare typer som inte uttryckligen tas upp i den här guiden som kan vara till hjälp beroende på användningsfallet. Att komma igång genom att känna till dessa typer täcker de flesta användningsfall. Det är en stark grund för att börja modellera din MongoDB-databas.

Det är viktigt att veta vilka datatyper som är tillgängliga för dig när du använder en databas så att du använder giltiga värden och arbetar på data med förväntade resultat. Det finns risker som du kan stöta på utan att skriva in din data ordentligt, som visas i Double kontra Decimal128 träning. Det är viktigt att tänka på detta innan du bestämmer dig för en viss typ.

Om du är intresserad av att kolla in Prisma med en MongoDB-databas kan du kolla in dataanslutningsdokumentationen.




  1. Hur man konfigurerar SELinux för MongoDB Replica Sets

  2. MongoDB-sökning när främmande fält är en samling objekt

  3. MongoDB:Hur definierar man ett schema?

  4. hur man itererar en mongomarkör i en loop i python