dagblog.
← Archiv

Stavíme infrastrukturu kolem MongoDB — model


V poslední době jsem strávil nějaký čas psaním a vymýšlením konceptu persistentní vrstvy, nástrojů a jejich implementace, který nám umožní ukládat JSON dokumenty do NoSQL databáze MongoDB. Dokumenty i kolekce nemají žádné schéma. To má za následek, nebo alespoň u nás mělo, a divil bych se kdyby to někdo začal používat nějak sofistikovaněji, že moc nepřemýšlíte o struktuře dokumentů a prostě je ukládáte jak se vám zrovna hodí. To je velice příjemné a nějaký čas s tím vydržíte. Problém nastane ve chvíli kdy potřebujete ty dokumenty začít zpracovávat automaticky, například chcete udělat zálohu dokumentů vztahujících se k určité entitě v systému a nebo potřebujete zjistit, že odkazované dokumenty existují. Jinými slovy bez modelu popisujícího dokumenty, kolekce a jejich vztahy se neobejdete. Samozřejmě pokud si to nechcete dělat ručně v kódu pro každý typ dokumentu.

My jsme si data uložená v MongoDB popsali jednoduchým modelem reprezentovaným JSON dokumentem, který je sám v MongoDB uložený. Tento model slouží jednak pro nástroje, které dělají servisní operace, jako zálohy a jejich obnovu, validaci dat, čištění pohrobků apod.m a zároveň jím chceme řídit (zatím není implementováno) vlastní persistentní vrstvu, kterou ukládáme dokumenty.

Struktura modelu vypadá následovně.

DocumentStorageModel reprezentuje vlastní model. Má verzi, která nám umožňuje otestovat kompatibilitu dat s ním asociovaných. Typickým příkladem je záloha, ze které se snažím obnovit data, a rád bych se přesvědčil, že aktuální data a tedy i runtime je kompatibilní, a nepotkají mě nepříjemnosti po jejich obnovení. Verzí se zároveň řídí například migrace dat.

DocumentStorageModel obsahuje seznam kolekcí Collection. Každá kolekce má jméno, pod kterým existuje v MongoDB. Zároveň má dokumentaci Documentation. Ta obsahuje lidský srozumitelný popis toho, jaký typ dokumentu je v ní uložený. Dále release, ve kterém vznikla a URI template, pod kterým je vystavený na REST API. Záróveň může mít kolekce asociovaný ToolHints. Ten umožňuje popsat kolekci z pohledu nástrojů pro vytváření a validaci její definice přímo v MongoDB. Například dočasná data se vkládají do takzvané Capped collection, která automaticky odmazává nejstarší vložené dokumenty. Díky těmto hintům je možné ověřit, že je kolekce skutečně tímhle způsobem zkonfigurovaná.

Dokumenty a jejich struktura je popsaná v DataDefinition. Pro jejich validaci je možné definovat RelaxNG schéma (více o tom psal Lukáš Křečan v článku Converting JSON to XML). To se dá použít jednak v persistentni vrstvě pro validaci při změnách/zápisu a zároveň i pro verifikaci například po migraci dat.

Samostatnou kapitolou jsou relace. Šťastnější pojmenování by bylo reference v tomhle případě, aby to v člověku nevyvolávalo pocit, že se snažíme modelovat svět relačních databází. Dokumenty mezi sebou odkazujeme pomocí URI referencí. Máme celkem tři druhy relací: sama na sebe (SelfDocumentRelation), interní na jiný dokument v MongoDB (InternalDocumentRelation) a externí na dokumenty/entity uložené mimo náš systém (ExternalDocumentRelation). Každá relace má u sebe dva atributy cestu k fieldu, ve kterém je v dokumentu uložena a URI template, pomocí které je jí možné rozložit na jednotlivé segmenty. To se používá ve chvíli kdy potřebujeme zjistit příslušnost dokumentu k projektu nebo uživateli. Jednoduchým rozpársováním pomocí URI template víme konkrétního uživatele nebo projekt, ke kterému se dokument vztahuje.

Ukázka modelu

{
"documentStorageModel":{
"collections":[
{
"collection":{
"name":"subscriptions",
"affiliation":"PROJECT",
"resourceUriTemplate":"/gdc/projects/{project}/users/{user}/subscriptions/{subscription}",
"documentation":{
"description":"Contains notification subscriptions for given user in given project",
"releaseVersion":"R59"
},
"dataDefinition":{
"self":{
"selfDocumentRelation":{
"path":"subscription.meta.uri",
"uriTemplate":"/gdc/projects/{project}/users/{user}/subscriptions/{subscription}"
}
}
}
}
}
... další kolekce
],
"version":"1.0.0"
}
}

Ukázka dokumentu popsaného modelem

{
"subscription" : {
"channels" : [
"/gdc/account/profile/xxx/channelConfigurations/4f4b7e5ce4b0413360a0c4d5"
],
"meta" : {
"title" : "Test subscription",
"author" : "/gdc/account/profile/xxx",
"category" : "subscription",
"updated" : "2012-02-27 14:00:12",
"created" : "2012-02-27 14:00:12",
"uri" : "/gdc/projects/FoodMartDemo/users/xxx/subscriptions/4f4b7e5ce4b0413360a0c4d7"
},
"message" : {
"template" : {
"expression" : "Hello World"
}
},
}
}

Z modelu je vidět, že v dokumentu by měl být field na cestě subscription.meta.uri a jeho hodnota by měla odpovídat URI template /gdc/projects/{project}/users/{user}/subscriptions/{subscription}. Z instance dokumentu je vidět, že tomu jak je viz /gdc/projects/FoodMartDemo/users/xxx/subscriptions/4f4b7e5ce4b0413360a0c4d7. Jednoduchou introspekcí této URI reference vidíme, že náleží k projektu FoodMartDemo.

Závěr

Cílem tohoto článku bylo nechat vás trochu nahlédnout do toho kam se v GoodData ubírá naše práce s NoSQL databází MongoDB. Potřeba modelu popisujícího data se ukázala jako nutnost. Na druhou stranu to není specifikum NoSQL světa, protože k podobné řešení, jsme již používali v HP SOA Systinet klasickou relační databází. Pokud máte podobné zkušenosti, a nebo naopak používáte jiný způsob k popisu dat a řízení nástrojů pro práci s nimi, určitě se podělte v komentářích pod tímto článkem.

Verze na Medium

Související články

Související epizody CZ Podcastu