sql >> Databáze >  >> NoSQL >> MongoDB

Úvod do datových typů MongoDB


Úvod

Při používání MongoDB máte možnost být flexibilní se strukturou vašich dat. Nejste vázáni udržováním určitého schématu, do kterého se musí vejít všechny vaše dokumenty. Pro každé dané pole v dokumentu můžete použít kterýkoli z dostupných typů dat podporováno MongoDB. Navzdory tomuto výchozímu způsobu práce můžete v MongoDB zavést schéma JSON a v případě potřeby přidat ověření do vašich sbírek. V této příručce se nebudeme zabývat podrobnostmi návrhu schématu, ale pokud je implementován, může mít vliv na typování dat.

Datové typy určují obecný vzor pro data, která přijímají a ukládají. Při plánování databáze je prvořadé porozumět tomu, kdy zvolit určitý datový typ před jiným. Zvolený typ bude určovat, jak můžete s daty pracovat a jak jsou uložena.



JSON a BSON

Než se dostaneme do podrobností o konkrétních typech dat, je důležité porozumět tomu, jak MongoDB ukládá data. MongoDB a mnoho dalších databází NoSQL založených na dokumentech používá JSON (JavaScript Object Notation) k reprezentaci datových záznamů jako dokumentů.

Použití JSON k ukládání dat má mnoho výhod. Některé z nich jsou:

  • snadné čtení, učení a důvěrnost mezi vývojáři
  • flexibilita formátu, ať už řídkého, hierarchického nebo hluboce vnořeného
  • samopopisující, což umožňuje aplikacím snadno pracovat s daty JSON
  • umožňuje zaměřit se na minimální počet základních typů

JSON podporuje všechny základní datové typy jako řetězec, číslo, boolean atd. MongoDB ve skutečnosti ukládá datové záznamy jako binárně kódované dokumenty JSON (BSON). Stejně jako JSON podporuje BSON vkládání dokumentů a polí do jiných dokumentů a polí. BSON umožňuje další typy dat, které nejsou pro JSON dostupné.



Jaké jsou datové typy v MongoDB?

Než půjdeme do podrobností, pojďme si udělat široký pohled na to, jaké datové typy jsou podporovány v MongoDB.

MongoDB podporuje řadu datových typů vhodných pro různé typy jednoduchých i komplexních dat. Patří mezi ně:

Text

  • String

Číselné

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

Datum/Čas

  • Date
  • Timestamp

Jiné

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

V MongoDB má každý typ BSON identifikátory celého čísla i řetězce. Nejběžnějšími z nich se budeme podrobněji zabývat v této příručce.



Typy řetězců

Typ řetězce je nejběžněji používaný datový typ MongoDB. Jakákoli hodnota zapsaná uvnitř dvojitých uvozovek "" v JSON je hodnota řetězce. Jakákoli hodnota, kterou chcete uložit jako text, bude nejlepší napsat jako String . Řetězce BSON jsou UTF-8 a jsou v MongoDB reprezentovány jako:

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

Obecně se ovladače pro programovací jazyky při serializaci a deserializaci BSON převedou z formátu řetězce jazyka na UTF-8. Díky tomu je BSON atraktivní metodou například pro snadné ukládání mezinárodních znaků.

Vložení dokumentu s String datový typ bude vypadat nějak takto:

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

Dotaz na kolekci vrátí následující:

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

Použití $type operátor

Než přejdeme k dalšímu datovému typu, je důležité vědět, jak můžete zadat, zkontrolovat hodnotu před provedením jakéhokoli vložení. Předchozí příklad použijeme k demonstraci pomocí $type operátor v MongoDB.

Řekněme, že už je to nějaký čas, co jsme pracovali s mytestcoll sbírka z dřívějška. Chceme do kolekce vložit nějaké další dokumenty s first_name pole. Abychom ověřili, že jsme použili String jako datový typ uložený jako hodnota first_name původně můžeme spouštět následující s použitím aliasu nebo číselné hodnoty datového typu:

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

Nebo

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

Oba dotazy vracejí výstup všech dokumentů, které mají String hodnota uložená pro first_name z vložení naší předchozí sekce:

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

Pokud se dotazujete na typ, který není uložen v first_name pole jakéhokoli dokumentu, nezískáte žádný výsledek. To znamená, že se jedná o jiný datový typ uložený v first_name .

Pomocí $type se také můžete dotazovat na více typů dat najednou operátor jako následující:

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

Protože jsme nevložili žádné Null zadejte hodnoty do naší kolekce, výsledek bude stejný:

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

Stejnou metodu můžete použít u všech následujících typů, o kterých budeme diskutovat.




Čísla a číselné hodnoty

MongoDB obsahuje řadu číselných datových typů vhodných pro různé scénáře. Rozhodnutí, který typ použít, závisí na povaze hodnot, které plánujete uložit, a na vašich případech použití pro data. JSON nazývá vše s čísly Číslem . To nutí systém zjistit, jak jej převést na nejbližší nativní datový typ. Začneme zkoumáním celých čísel a toho, jak fungují v MongoDB.


Celé číslo

Integer datový typ se používá k ukládání čísel jako celých čísel bez zlomků nebo desetinných míst. Celá čísla mohou být kladné nebo záporné hodnoty. V MongoDB existují dva typy, 32-Bit Integer a 64-Bit Integer . Mohou být reprezentovány dvěma způsoby znázorněnými v tabulce níže, number a alias :

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

Rozsahy, do kterých se hodnota pro každý typ vejde, jsou následující:

  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

Výše uvedené typy jsou omezeny svým platným rozsahem. Jakákoli hodnota mimo rozsah bude mít za následek chybu. Vložení Integer zadejte do MongoDB bude vypadat takto:

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

A nalezení výsledku vrátí následující:

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

Jak napovídají názvy, 32-Bit Integer má 32 bitů s přesností celého čísla, což je užitečné pro menší celočíselné hodnoty, které nechcete ukládat jako posloupnost číslic. Při zvětšování velikosti čísla můžete dosáhnout až 64-Bit Integer který má 64bitovou celočíselnou přesnost a hodí se pro stejný případ použití jako první.



Dvojité

V BSON, výchozí náhrada za Číslo JSON je Double datový typ. Double datový typ se používá k uložení hodnoty s plovoucí desetinnou čárkou a může být reprezentován v MongoDB takto:

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

Čísla s plovoucí desetinnou čárkou jsou dalším způsobem vyjádření desetinných čísel, ale bez přesné a konzistentní přesnosti.

Čísla s plovoucí desetinnou čárkou mohou pracovat s velkým počtem desetinných míst efektivně, ale ne vždy přesně. Následuje příklad zadávání dokumentu pomocí Double zadejte do své sbírky:

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

Při výpočtu s dvojnásobkem mohou existovat nepatrné rozdíly mezi vstupem a výstupem, které mohou potenciálně vést k neočekávanému chování. Při provádění operací, které vyžadují přesné hodnoty, má MongoDB přesnější typ.



Desetinné číslo128

Pokud pracujete s velmi velkými čísly se spoustou rozsahu s pohyblivou řádovou čárkou, pak Decimal128 Datový typ BSON bude nejlepší volbou. Toto bude nejužitečnější typ pro hodnoty, které vyžadují velkou přesnost, jako v případech použití zahrnujících přesné peněžní operace. Decimal128 typ je reprezentován jako:

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

Typ BSON, Decimal128 , poskytuje 128bitovou desetinnou reprezentaci pro ukládání čísel, kde je přesné zaokrouhlování desetinných míst důležité. Decimal128 podporuje 34 desetinných míst s přesností nebo sinificand s rozsahem -6143 až +6144. To umožňuje vysokou míru přesnosti.

Vložení hodnoty pomocí Decimal128 datový typ vyžaduje použití NumberDecimal() konstruktor s vaším číslem jako String aby MongoDB nepoužíval výchozí číselný typ, Double .

Zde si ukážeme toto:

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

Při dotazu na kolekci pak získáte následující návrat:

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

Číselná hodnota si zachovává svou přesnost a umožňuje přesné operace. Pro demonstraci Decimal128 typu versus Double , můžeme projít následujícím cvičením.



Jak lze ztratit přesnost na základě datového typu

Řekněme, že chceme vložit číslo s mnoha desítkovými hodnotami jako Double do MongoDB pomocí následujícího:

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

Když se dotazujeme na tato data, dostaneme následující výsledek:

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

Tato hodnota se zaokrouhlí nahoru na 9999999.5 , ztrácí svou přesnou hodnotu, kterou jsme do něj zadali. Tím se vytvoří Double nevhodné pro ukládání čísel s mnoha desetinnými místy.

Následující příklad ukazuje, kde se přesnost ztratí při předávání Double implicitně s Decimal128 místo String jako v předchozím příkladu.

Začneme vložením následujícího Double znovu, ale pomocí NumberDecimal() aby to bylo Decimal128 typ:

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

Poznámka :Při provádění tohoto vložení do prostředí MongoDB se zobrazí následující varovná zpráva:

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

Tato varovná zpráva znamená, že číslo, které se pokoušíte předat, může být předmětem ztráty přesnosti. Navrhují použít String pomocí NumberDecimal() abyste neztratili žádnou přesnost.

Pokud varování ignorujeme a dokument přesto vložíme, bude ve výsledcích dotazu vidět ztráta přesnosti ze zaokrouhlení hodnoty nahoru:

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

Pokud se budeme řídit doporučeným NumberDecimal() přístup pomocí String se zachováním přesnosti uvidíme následující výsledky:

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

Pro jakýkoli případ použití vyžadující přesné a přesné hodnoty by tento návrat mohl způsobit problémy. Jakákoli práce zahrnující peněžní operace je příkladem, kdy přesnost bude extrémně důležitá a přesné hodnoty jsou rozhodující pro přesné výpočty. Tato ukázka zdůrazňuje, jak je důležité vědět, který typ číselných dat bude pro vaše data nejvhodnější.




Datum

Date BSON datový typ je 64bitové celé číslo, které představuje počet milisekund od epochy Unixu (1. ledna 1970). Tento datový typ ukládá aktuální datum nebo čas a lze jej vrátit jako objekt data nebo jako řetězec. Date je v MongoDB zastoupen následovně:

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

Poznámka :BSON Date typ je podepsán. Záporné hodnoty představují data před rokem 1970.

Hodnoty data lze vrátit třemi způsoby.

  1. Date() - vrátí řetězec

  2. new Date() - vrátí objekt data pomocí ISODate() obal

  3. ISODate() - také vrátí objekt data pomocí ISODate() obal

Níže uvádíme tyto možnosti:

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

A při návratu:

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


Časové razítko

Je zde také Timestamp datový typ v MongoDB pro reprezentaci času. Nicméně Timestamp bude nejužitečnější pro interní použití a není spojené s Date typ. Samotný typ je posloupnost znaků používaná k popisu data a času, kdy k události dojde. Timestamp je 64bitová hodnota, kde:

  • nejvýznamnějších 32 bitů je time_t hodnota (sekundy od epochy Unixu)
  • nejméně významných 32 bitů je inkrementující ordinal pro operace během dané sekundy

Jeho reprezentace v MongoDB bude vypadat následovně:

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

Při vkládání dokumentu, který obsahuje pole nejvyšší úrovně s prázdnými časovými razítky, MongoDB nahradí prázdnou hodnotu časového razítka aktuální hodnotou časového razítka. Výjimkou je, pokud _id pole obsahuje prázdné časové razítko. Hodnota časového razítka bude vždy vložena tak, jak je, a nebude nahrazena.

Vložení nového Timestamp hodnota v MongoDB použije new Timestamp() funkce a vypadat nějak takto:

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

Při dotazu na kolekci vrátíte výsledek podobný:

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


Objekt

Object datový typ v MongoDB se používá pro ukládání vložených dokumentů. Vložený dokument je řada vnořených dokumentů v key: value párový formát. Demonstrujeme Object zadejte níže:

var classGrades = {"Physics": 88, "German": 92, "LitTheoery": 79}db.mytestcoll.insertOne({student_name: "John Smith", report_card: classGrades}){        "acknowledged": true,        "insertedId": ObjectId("614b37296a124db40ae74d18")}

Poté si můžeme prohlédnout náš nový dokument:

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

Object datový typ optimalizuje pro ukládání dat, ke kterým je nejlepší přistupovat společně. Poskytuje určitou efektivitu v oblasti úložiště, rychlosti a odolnosti na rozdíl od ukládání každé značky třídy z výše uvedeného příkladu samostatně.



Binární data

Binary Data nebo BinData , datový typ dělá přesně to, co jeho název napovídá, a ukládá binární data pro hodnotu pole. BinData se nejlépe používá, když ukládáte a vyhledáváte data, kvůli jeho účinnosti při reprezentaci bitových polí. Tento datový typ lze reprezentovat následujícími způsoby:

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

Zde je příklad přidání některých Binary data do dokumentu ve sbírce:

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

Chcete-li zobrazit výsledný dokument:

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


ObjectId

ObjectId typ je specifický pro MongoDB a ukládá jedinečné ID dokumentu. MongoDB poskytuje _id pole pro každý dokument. ObjectId má velikost 12 bajtů a může být reprezentováno následovně:

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

ObjectId se skládá ze tří částí, které tvoří jeho 12bajtový makeup:

  • 4bajtovou hodnotu časového razítka , představující vytvoření ObjectId, měřeno v sekundách od epochy Unix
  • 5bajtová náhodná hodnota
  • 3bajtové přírůstkové počítadlo inicializován na náhodnou hodnotu

V MongoDB vyžaduje každý dokument v kolekci jedinečné _id fungovat jako primární klíč. Pokud _id ponecháte prázdné pole pro vložený dokument, MongoDB automaticky vygeneruje ObjectId pro pole.

Použití ObjectId pro _id má několik výhod :

  • v mongosh (MongoDB shell), čas vytvoření ObjectId je přístupný pomocí ObjectId.getTimestamp() metoda.
  • třídění podle _id pole, které ukládá ObjectId datové typy jsou blízkým ekvivalentem třídění podle času vytvoření.

V příkladech jsme zatím viděli ObjectId a budou vypadat podobně jako toto:

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

Poznámka :Hodnoty ObjectId by se měly časem zvyšovat, nemusí však být nutně monotónní. Je to proto, že:

  • Obsahují pouze jednu sekundu časového rozlišení, takže hodnoty vytvořené během stejné sekundy nemají zaručené pořadí
  • hodnoty jsou generovány klienty, kteří mohou mít různé systémové hodiny


Booleovský

MongoDB má nativní Boolean datový typ pro ukládání pravdivých a nepravdivých hodnot v rámci kolekce. Boolean v MongoDB může být reprezentován následovně:

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

Vložení dokumentu s Boolean datový typ bude vypadat nějak takto:

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

Při hledání dokumentu se výsledek zobrazí jako:

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


Regulární výraz

Regular Expression datový typ v MongoDB umožňuje ukládání regulárních výrazů jako hodnoty pole. MongoDB používá jako jazyk regulárních výrazů PCRE (Perl Compatible Regular Expression).

Může být reprezentován následujícím způsobem:

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

BSON vám umožňuje vyhnout se typickému kroku „převod z řetězce“, který se běžně vyskytuje při práci s regulárními výrazy a databázemi. Tento typ bude nejužitečnější při psaní databázových objektů, které vyžadují ověřovací vzory nebo odpovídající spouštěče.

Můžete například vložit Regular Expression datový typ, jako je tento:

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

Tato sekvence příkazů přidá tyto dokumenty do vaší sbírky. Poté můžete dotazovat svou sbírku a najít vložené dokumenty:

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

Vzory regulárních výrazů jsou uloženy jako regulární výraz, nikoli jako řetězce. To vám umožní dotazovat se na konkrétní řetězec a získat vrácené dokumenty, které mají regulární výraz odpovídající požadovanému řetězci.



JavaScript (bez rozsahu)

Podobně jako dříve zmíněný Regular Expression datový typ, BSON umožňuje MongoDB ukládat funkce JavaScriptu bez rozsahu jako svůj vlastní typ. JavaScript typ lze rozpoznat následovně:

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

Přidání dokumentu do sbírky pomocí JavaScript datový typ bude vypadat nějak takto:

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

Tato funkce vám umožňuje ukládat funkce JavaScriptu uvnitř vašich sbírek MongoDB, pokud je to potřeba pro konkrétní případ použití.

Poznámka :S MongoDB verze 4.4 a vyšší, alternativní typ JavaScriptu, JavaScript with Scope datový typ, byl zastaralý



Závěr

V tomto článku jsme probrali většinu běžných datových typů, které jsou užitečné při práci s databázemi MongoDB. Existují další typy, které nejsou výslovně uvedeny v této příručce, které mohou být užitečné v závislosti na případu použití. Začněte tím, že budete znát tyto typy, pokrývá většinu případů použití. Je to pevný základ pro zahájení modelování databáze MongoDB.

Je důležité vědět, jaké datové typy máte při používání databáze k dispozici, abyste mohli používat platné hodnoty a pracovat s daty s očekávanými výsledky. Existují rizika, na která můžete narazit bez správného zadání dat, jak je ukázáno v Double versus Decimal128 cvičení. Je důležité na to myslet ještě předtím, než se pustíte do jakéhokoli daného typu.

Pokud máte zájem vyzkoušet Prismu s databází MongoDB, můžete se podívat na dokumentaci datového konektoru.




  1. Faktory, které je třeba zvážit při výběru MongoDB pro aplikace s velkým objemem dat

  2. Jak určit únik paměti Redis?

  3. Mongoose řetězec na ObjectID

  4. MongoDB $konvertovat