Ú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.
-
Date()
- vrátí řetězec -
new Date()
- vrátí objekt data pomocíISODate()
obal -
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.