Dokumentově orientovaná databáze
- data ukládá v BSON (binární JSON)
Architektura
- máme server, databáze, kolekce (logický kontejner pro dokumenty, ekvivalent tabulky) a dokumenty (jsou ve formátu klíč-hodnota i s vnořenými a složitými strukturami)
- instance → databases → collections → documents
- collection sdružuje více dokumentů, většinou s podobnou strukturou
- jeden dokument = 1 JSON object (jakkoliv složitý a velký)
Sharding
- automatická distribuce dat mezi více uzlů clusteru
- master-slave architektura
- na jednotlivých uzlech jsou shardy
- shard je implementován jako replikační set pro zajištění dostupnosti
- data se rozdělují pomocí sharding klíčů
- součástí jsou konfigurační servery, které udržují metadata o rozložení dat v clusteru
- součástí jsou Mongo Routery = příjímají dotazy od klienta a přeposílají je na konkrétní shardy + vrací data klientovi
Replikace
- v rámci replikačního setu máme primární uzel a sekundární uzly
- primární přijímá všechny zápisy
- sekundární obsahují kopie dat a slouží k obsluze dat na čtení
- po selhání primárního uzlu je jeden ze sekundárních uzlů povýšený na primární
- pomocí algoritmu volby (quorum)
Indexy
- optimalizace výkonu dotazů, redukují množství prohledávaných dat
- bez indexu se provádí full collection scan
- máme jednoduché (na jednom poli dokumentu) a složené (na více polích najednou)
- multikey indexy - na pole obsahující pole nebo vnořené pole
- mám pak index na každou hodnotu v poli
- textové indexy - pro fulltextové vyhledávání
- geospatiální indexy - na geolokační data
- pozor - indexy jsou náročné na místo na disku
Datový model
_idje rezervován pro primární klíč (unikátní v rámci jedné collection)- většinou je datovým typem
ObjectId, speciální 12 bajtový BSON typ - ale datový typ může být cokoliv kromě JSON Array
- je immutable
- většinou je datovým typem
$je rezervováno pro query operace (nesmí být na začátku nějakého identifikátoru)- identifikátory také nesmí obsahovat tečku
.(ta se používá pro přístup ke vnořeným polím)
- identifikátory také nesmí obsahovat tečku
- názvy polí musí být unikátní
- není žádné explicitní schéma dat, ale vzhledem k použití v aplikacích tam nějaké implicitní schéma je (aby to mělo cca aspoň nějakou strukturu a dalo se to spolehlivě používat)
- 2 možnosti designu datového modelu:
- denormalizovaný datový model
- related data jsou v jednom dokumentu (jako vnořené subdokumenty)
- dobré pro one-to-one nebo one-to-many vztahy
- možné data redundancies, méně queries potřeba
- normalizovaný datový model
- related data jsou v různých dokumentech a jsou provázané pomocí “References”
- např.
actors: [ObjectId("6"), ObjectId("15")]
- např.
- dobré pro many-to-many
- lépe organizované, více queries potřeba
- related data jsou v různých dokumentech a jsou provázané pomocí “References”
- denormalizovaný datový model
Dotazy
- query language je JavaScript
- dotazy se provádí vždy nad konkrétní collection
- read dotazy vrátí tzv. “cursor”, pointer na výslednou množinu dokumentů (tj. nenahrajou se rovnou do paměti, ale mám na ně ukazatel a můžu si je procházet)
- tím pádem mohu za
findřetězitsort(), skip(), limit()
- tím pádem mohu za
- CRUD
- inserting - pokud specifikovaná collection neexistuje, tak se vytvoří
- vkládaný
_idmusí být unikátní, pokud tam není, tak se automaticky vytvoříObjectId
- vkládaný
- replacing - pokud více dokumentů vyhovuje dotazu, tak se nahradí pouze první nalezený
- dokument se nahradí celý
- upsert mode - pokud se najde dokument → replace, pokud se nenajde → insert
{ upsert: true }
- updating
- vybere se dokument/dokumenty, které se budou aktualizovat
- pak následuje seznam úprav:
- používá se
$set,$inc,$unset,$renameatd. - pro Arrays:
$push,$addToSet,$pop,$pull
- používá se
- také existuje upsert mode
- pokud se bude vytvářet, tak nový dokument bude obsahovat všechny hodnoty z query části, upravené o hodnoty ze seznamu úprav
- finding
- selection - když děláme selekci na shodnot hodnot, tak musí být úplně identické
- dva typy:
- value equality = porovnávání hodnot
- objekty musí být 100 % identické
- i co se týče čísel, pořadí, názvy rekurzivních vnořených objektů apod.
- objekty musí být 100 % identické
- query operators = na základě definovaných podmínek
- value equality = porovnávání hodnot
- dva typy:
- projection
_idse nachází defaultně ve výsledku, lze ho odstranit pomocí_id: falseor_id: 0- pole s
true/1jsou included - pole s
false/0jsou excluded- nesmí se to míchat dohromady, musím si vybrat, jestli chci vybírat ty, co budou included a nebo vybírat ty, co budou excluded
- modifiers - mění pořadí a množství výstupních dokumentů
- sort - sortování se provádí před projekcí (tj. nezobrazená pole mohou být použita k řazení)
- 1 pro ascending, -1 for descending
- skip - přeskoč X dokumentů od začátku odpovědi
- limit
- sort - sortování se provádí před projekcí (tj. nezobrazená pole mohou být použita k řazení)
- selection - když děláme selekci na shodnot hodnot, tak musí být úplně identické
- inserting - pokud specifikovaná collection neexistuje, tak se vytvoří
Výhody
- flexibilita (různé dokumenty v jedné kolekci)
- škálovatelné - horizontální škálování pomocí shardingu
- výkon
- vnořené dokumenty - můžu reprezentovat složité struktury a nemusím joinovat
Nevýhody
- nezaručená integrita dat
- nadbytek dat - můžou vznikat redundance
- složitější správa clusteru
- absence joinů - dotazování se napříč kolekcemi je složitější
Validační schéma
- pokud chceme specifikovat různé datové typy, povinnost jednotlivých properties či rozsah hodnot
- úrovně vynucování validace:
- strict - pokud dokument nevyhovuje validačnímu schématu - operace selže
- moderate - operace selže jenom při explicitní změně nevyhovujících polí
- takže můžeme vkládat dokumenty, které nevyhovují schématu
- díky validačnímu schématu máme kvalitnější data, minimum chyb (aplikace nepracuje s nevalidními daty) a lepší údržba (máme očekávatelný formát)
db.createCollection("uzivatele", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["jmeno", "vek"],
properties: {
jmeno: {
bsonType: "string",
description: "Jméno uživatele musí být text"
},
vek: {
bsonType: "int",
minimum: 0,
maximum: 120,
description: "Věk musí být celé číslo v rozsahu 0–120"
},
email: {
bsonType: "string",
pattern: "^.+@.+$",
description: "Email musí být validní"
}
}
}
}
});
CAP teorém
- splňuje garanci CP