Přejít k navigační liště

Zdroják » Databáze » Kompletní průvodce po CouchDB – IV

Kompletní průvodce po CouchDB – IV

Články Databáze

V této kapitole probereme detailněji práci s CouchDB API, ukážeme si osvědčené postupy a provedeme vás přes obvyklé pasti. Začneme základními operacemi, popsanými v minulé kapitole, a podíváme se, co se děje pod pokličkou a co používá Futon k tomu, aby vám mohl nabídnout všechny ty pěkné funkce.

Nálepky:

Core API

Tato kapitola je popisem jádra CouchDB API a zároveň referencí. Pokud si nebudete moci vzpomenout, jak spustit určitý dotaz nebo jaké parametry jsou potřeba, podívejte se do této kapitoly a zjistíte, jak se věci mají (sami jsme pravděpodobně nejčastějšími čtenáři této kapitoly).

Během popisování základních kousků API budeme muset vzít výklad občas větší oklikou a vysvětlit důvody, které vedly k volbě určitého postupu. To je zároveň dobrá příležitost vysvětlit si, proč CouchDB pracuje tak, jak pracuje.

API můžeme rozdělit do několika sekcí. Projdeme si je individuálně:

  • Server
  • Databáze
  • Dokumenty
  • Replikace

Server

Tato část API je jednoduchá. Nabízí kontrolu instalace, pomocí níž uvidíte, jestli CouchDB vůbec běží. Můžete ji rovněž použít tehdy, když se chcete ujistit, že běží verze, kterou požadujete. Opět použijeme   curl:

curl http://127.0.0.1:5984/

CouchDB odpoví:

{"couchdb":"Welcome","version":"0.10.1"}

Dostáváte řetězec ve formátu JSON, který, když jej rozparsujete do objektu nebo jiné datové struktury dle použitého jazyka, obsahuje „uvítací řetězec“ a informace o verzi.

Není to nějak úžasně užitečné, ale pěkně to ilustruje způsob, jak se CouchDB chová. Pošlete HTTP požadavek, a server vrátí JSON řetězec v HTTP odpovědi coby výsledek.

Databáze

Pojďme udělat něco užitečnějšího: vytvořit databáze. CouchDB je, přesně řečeno, database management system (DMS). To znamená, že dokáže spravovat více databází. Databáze je nádoba, která uchovává „příbuzná data“. Později si ukážeme přesný význam těchto slov. V praxi se terminologie překrývá – slovem „databáze“ lidé označují jak samotný DMS, tak i data, která jsou v DMS uložená. Budeme se ve výkladu držet tohoto nejednoznačného významu, takže se tím nenechte mást. Většinou by z kontextu mělo být naprosto jasné, jestli hovoříme o celé CouchDB nebo o jedné databázi v CouchDB uložené.

Jednu si teď vytvoříme. Budeme chtít uložit oblíbená hudební alba a dáme databázi vysoce originální název albums. Všimněte si, že používáme parametr -X, abychom vysvětlili utilitě curl, že má poslat dotaz typu PUT namísto obvyklého  GET:

curl -X PUT http://127.0.0.1:5984/albums

CouchDB odpoví:

{"ok":true}

A je to! Vytvořili jste databázi a CouchDB vám oznámila, že vše dopadlo dobře. Co se stane, když budete vytvářet databázi, která už existuje? Zkusíme znovu:

curl -X PUT http://127.0.0.1:5984/albums

CouchDB odpoví:

{"error":"file_exists","reason":"The database could not be created, the file already exists."}

Dostaneme chybové hlášení. To dá rozum. Navíc zjišťujeme, že CouchDB ukládá databáze do souborů, co databáze, to soubor. Jednoduché. Tento přístup má nějaké další důsledky, ale ty teď vynecháme a podrobně si je popíšeme v Příloze F, Síla B-trees.

Vytvoříme si další databázi, a tentokrát použijeme volbu -v (“verbose”). Tato volba požaduje po curl, aby ukázal nikoli jen základní informace, tedy tělo HTTP odpovědi, ale všechny související detaily:

curl -vX PUT http://127.0.0.1:5984/albums-backup

curl vypíše:

* About to connect() to 127.0.0.1 port 5984 (#0)
*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)
> PUT /albums-backup HTTP/1.1
> User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
> Host: 127.0.0.1:5984
> Accept: */*
>
< HTTP/1.1 201 Created
< Server: CouchDB/0.9.0 (Erlang OTP/R12B)
< Date: Sun, 05 Jul 2009 22:48:28 GMT
< Content-Type: text/plain;charset=utf-8
< Content-Length: 12
< Cache-Control: must-revalidate
<
{"ok":true}
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

Opravdu upovídané! Projděme si to řádek po řádku a ukažme si, co se vlastně děje a co je důležité. Když pár takových výpisů uvidíte, budete si důležitých věcí všímat mnohem snáz.

* About to connect() to 127.0.0.1 port 5984 (#0)

Zde curl oznamuje, že zahajuje spojení přes TCP k CouchDB serveru, který jsme specifikovali v URI. Není to nijak významné, pokud tedy nehledáme chyby v síťovém provozu.

*   Trying 127.0.0.1... connected
* Connected to 127.0.0.1 (127.0.0.1) port 5984 (#0)

curl hlásí úspěšné spojení s CouchDB. Opět – není to nijak důležité, pokud nehledáme chyby v připojení.

Další řádky mají prefix > a <. > označuje obsah poslaný do CouchDB (samosebou bez >). < analogicky označuje řádky, které poslala CouchDB zpět.

> PUT /albums-backup HTTP/1.1

Začátek HTTP požadavku. Použitá metoda je PUT, URI je /albums-backup a je použit protokol HTTP verze HTTP/1.1. Existuje i HTTP/1.0, který je o něco jednodušší v některých případech, ale vy používejte  HTTP/1.1.

Dále vidíme několik hlaviček požadavků. Ty poskytují CouchDB některé doplňkové informace o požadavku.

> User-Agent: curl/7.16.3 (powerpc-apple-darwin9.0) libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3

User-Agent říká, jaký klientský SW posílá tento požadavek. Neřeklo nám to nic nového: je to curl. Tato hlavička může být užitečná v případech, když víme, že určitý klient obsahuje chybu a server se na to může připravit. Rovněž informuje o použité platformě a můžete si z ní dělat statistiky. Pro CouchDB je hlavička User-Agent naprosto nedůležitá.

> Host: 127.0.0.1:5984

Hlavička Host je vyžadována HTTP 1.1. Oznamuje serveru jméno požadovaného hostitele (v případě, že jeden stroj obsluhuje víc hostitelů).

> Accept: */*

Hlavička Accept říká CouchDB, že curl akceptuje libovolný typ odpovědi. Za chvilku si ukážeme, k čemu to může být užitečné.

>

Prázdný řádek označuje konec hlaviček. Zbytek požadavku jsou data, která posíláme serveru. My neposíláme tentokrát žádná data, takže zbytek už jsou odpovědi od serveru.

< HTTP/1.1 201 Created

První řádek odpovědi od CouchDB obsahuje číslo verze HTTP protokolu (znovu – jako potvrzení že server umí pracovat s požadovanou verzí), stavový kód HTTP a stavovou zprávu. Různé požadavky mohou dostat různé odpovědi. Je jich velké množství a oznamují klientu (v našem případě curl), co server s požadavkem udělal, popřípadě, pokud nastala chyba, jaký druh chyby to byl. RFC 2616 (specifikace HTTP 1.1) definuje jednotlivé stavové kódy a chování. CouchDB tuto specifikaci plně respektuje.

Stavový kód 201 Created oznamuje klientovi, že požadavek na vytvoření zdroje (resource) dopadl úspěšně a požadovaný objekt (zdroj) byl vytvořen. To není překvapivé, ale pokud se pamatujete na chybové hlášení, které jsme dostali, když jsme vytvářeli existující databázi, tak to mělo zde jiný stavový kód. Reakce na stavový kód je poměrně běžnou praxí. Například kódy s hodnotou 400 a vyšší oznamují, že došlo k nějaké chybě. Pokud chcete zjednodušit logiku a chybu rozpoznat rychleji než z vráceného obsahu, prostě zkontrolujte stavový kód, pokud je >= 400, došlo k chybě.

< Server: CouchDB/0.10.1 (Erlang OTP/R13B)

Hlavička Server je dobrá k diagnostice. Oznamuje verzi CouchDB a verzi jazyka Erlang. Můžeme ji v běžné praxi ignorovat, ale je dobré vědět, že tu je.

< Date: Sun, 05 Jul 2009 22:48:28 GMT

Date oznamuje serverový datum a čas. Protože klient a server mohou mít každý jiný čas, je tato hlavička čistě informativní a neměli byste na ní stavět žádné důležité rozhodnutí!

< Content-Type: text/plain;charset=utf-8

Hlavička Content-Type říká, jaký MIME typ je obsažen v těle HTTP odpovědi a jak je kódována. Víme, že CouchDB vrací řetězce typu JSON. Odpovídající Content-Type je application/json. Proč tu tedy je text/plain? Je to jedna ze situací, kde pragmatismus vyhrál nad purismem: když pošlete application/json, prohlížeč nabídne stažení souboru namísto jeho zobrazení. Protože je užitečné mít možnost testovat CouchDB přímo v prohlížeči, posílá CouchDB odpověď jako text/plain, takže prohlížeče neotvírají ukládací dialog, ale zobrazují JSON jako text.

Existují rozšíření pro prohlížeče, které se umí s JSON vypořádat, ale nebývají instalovaná.

Pamatujete na hlavičku Accept a na to, jak jsme pomocí */* vyjadřovali, že server může poslat jakoukoli odpověď? Pokud pošlete Accept: application/json, bude CouchDB vědět, že dokážete zpracovat JSON se správným MIME typem, a použije tedy správný Content-Type namísto  text/plain.

< Content-Length: 12

Hlavička Content-Length udává velikost těla odpovědi v bajtech.

< Cache-Control: must-revalidate

Tento údaj v hlavičce Cache-Control říká vám nebo jakémukoli proxy serveru, že obsah odpovědi nemá být cachován.

<

Prázdný řádek ukončuje hlavičky a oznamuje, že zbytek už je samotné tělo odpovědi.

{"ok":true}

A to je to, co už známe.

* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0

Posledními dvěma řádky opět curl hlásí, že udržoval otevřené TCP spojení a po obdržení odpovědi jej uzavřel.

V dalším textu občas použijeme opět přepínač -v, ale některé hlavičky, které nejsou podstatné, z výpisu vynecháme a ponecháme pouze ty, které jsou důležité pro daný případ.

Vytváření databází je skvělé a úžasné, ale co když jsme nějakou databází už unavení? Snadné – prostě změníme HTTP metodu:

> curl -vX DELETE http://127.0.0.1:5984/albums-backup

Tento požadavek smaže CouchDB databázi a odstraní soubor, v němž byla uložena. Všimněte si, že tu není žádná bezpečnostní pojistka, žádné „Opravdu chcete databázi smazat?“ ani odpadkový koš. Používejte proto tento příkaz opatrně. Pokud si databázi smažete, bude smazaná a bez zálohy dat nemáte šanci ji opět obnovit.

V této sekci jsme se podívali podrobněji na HTTP a připravili se na popis zbývajících základních částí API. Příští zastávka: dokumenty.

Dokumenty

Dokumenty jsou hlavní datovou strukturou CouchDB. Jejich hlavní myšlenka je, nepřekvapivě, podobná dokumentům z reálného světa. List papíru s fakturou, objednávka, vizitka. Už jsme si ukazovali, že CouchDB používá pro ukládání formát JSON. Ukažme si, jak to chodí na té nejnižší úrovni.

Každý dokument v CouchDB má ID. Tento identifikátor, ID, je v databázi unikátní. Můžete si vybrat jakýkoli řetězec, ale doporučujeme použít zaručeně unikátní UUID (nebo GUID), tedy Universally (nebo Globally) Unique IDentifier. UUID jsou náhodná čísla s velmi nízkou pravděpodobností opakování, takže kdokoli může vytvářet tisíce  UUID za minutu po spoustu let aniž by vytvořil duplikát. To je skvělý způsob, jak se ujistit, že dva různí lidé nemohou vytvořit dva různé dokumenty se stejným ID. Proč by vás mělo zajímat, jestli někdo jiný něco takového nedělá? No, zaprvé tím „někým jiným“ můžete být vy sami o chvíli později z jiného počítače, a zadruhé: replikace CouchDB umožňuje sdílet dokumenty s ostatními a UUID zajišťují, že to vše bude fungovat. Ale o tom si povíme později, teď pojďme vytvořit nějaké ty dokumenty:

curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"title":"There is Nothing Left to Lose","artist":"Foo Fighters"}'

CouchDB odpovídá:

{"ok":true,"id":"6e1295ed6c29495e54cc05947f18c8af","rev":"1-2902191555"}

Příkaz curl vypadá složitě, ale jen na první pohled. Rozeberme si ho na části. Nejprve příznak -X PUT řekne curl, aby poslal požadavek PUT. Následuje URL, kde je IP adresa databáze a port. Část URL, která označuje resource, /albums/6e1295ed6c29495e54cc05947f18c8af, udává umístění dokumentu v databázi albums. Ta divoká změť čísel a znaků je UUID, a toto UUID je ID vašeho dokumentu. Konečně přepínač -d oznamuje curl, aby to, co je za ním, použil jako tělo dotazu PUT. Následující řetězec je prostý JSON, který obsahuje atributy title a artist a jejich hodnoty.

Pokud nemáte po ruce vhodné UUID, můžete CouchDB o jeden požádat. Jednoduše pošlete GET požadavek na adresu  /_uuids:

curl -X GET http://127.0.0.1:5984/_uuids

a CouchDB vám vrátí požadované:

{"uuids":["6e1295ed6c29495e54cc05947f18c8af"]}

Voila, UUID. Pokud jich potřebujete víc, řekněte si, stačí předat počet v parametru count: ?count=10 vrátí 10 UUID – můžete si samosebou říct o jakýkoli rozumný počet.

Ujistíme se, že CouchDB nelže (obvykle to nedělá) a zkusíme tentýž dokument přečíst pomocí požadavku GET:

curl -X GET http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af

Vidíte určitý vzor? Vše v CouchDB má nějakou adresu, URI, a používáme různé HTTP metody, kterými s těmito URI pracujeme.

CouchDB odpovídá:

{"_id":"6e1295ed6c29495e54cc05947f18c8af","_rev":"1-2902191555","title":"There is Nothing Left to Lose","artist":"Foo Fighters"}

Je to hodně podobné tomu dokumentu, který jsme ukládali, což je dobře. Ale vidíte, že CouchDB přidala dvě pole. První je _id, které obsahuje UUID, s nímž jsme si přáli dokument uložit. Dokument tedy sám obsahuje svoje ID, což je užitečné.

Druhé pole je _rev. Obsahuje číslo revize.

Revize

Chceme-li změnit dokument v CouchDB, neříkáme databázi, aby šla a vyhledala určité pole v určitém dokumentu a tam zapsala novou hodnotu.  Místo toho si přečteme celý dokument z CouchDB, uděláme požadované změny v JSON a uložíme jej opět celý jako novou verzi (revizi) dokumentu do CouchDB. Každá taková revize je označena novým číslem v atributu  _rev.

Pokud chcete nahrát nebo smazat určitý dokument, bude CouchDB očekávat, že vložíte do pole _rev číslo revize dokumentu, který si přejete změnit. Jakmile CouchDB změnu přijme, vygeneruje nové číslo revize. Tento mechanismus zajišťuje, že v případě, když někdo změnil dokument v čase od jeho vyzvednutí do pokusu o změnu, odmítne CouchDB novou verzi, protože by mohlo dojít k nevítanému přepsání dat, o nichž jste nevěděli, že existují. Jinými slovy: kdo uloží změny jako první, vyhrává. Podívejme se, co se stane, pokud nezadáme hodnotu revize _rev (což odpovídá situaci, kdy zadáte zastaralou revizi):

curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"title":"There is Nothing Left to Lose","artist":"Foo Fighters","year":"1997"}'

CouchDB odpoví:

{"error":"conflict","reason":"Document update conflict."}

Pokud vidíte toto hlášení, přidejte číslo poslední revize do JSON:

curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d '{"_rev":"1-2902191555","title":"There is Nothing Left to Lose", "artist":"Foo Fighters","year":"1997"}'

Teď vidíte, k čemu se nám hodilo, že CouchDB vrací _rev při žádosti o dokument. CouchDB odpovídá:

{"ok":true,"id":"6e1295ed6c29495e54cc05947f18c8af","rev":"2-2739352689"}

CouchDB přijala vaši změnu a zároveň vygenerovala nové číslo revize. Číslo revize je hash čísla dokumentu s prefixem, který určuje, kolikrát byl dokument updatován. Tento postup se hodí při replikaci. Více v Kapitole 17, Správa konfliktů.

Je víc důvodů, proč CouchDB používá tento systém revizí, zvaný též Multi-Version Concurrency Control (MVCC). Jdou spolu ruku v ruce, a toto je dobrá příležitost si některé z nich představit.

Jedním z rysů HTTP protokolu, který používá CouchDB pro komunikaci, je, že je bezstavový. Co to znamená? Když komunikujete s CouchDB, posíláte požadavky. Poslání požadavku otevře síťové spojení s CouchDB, přenese nějaká data tam a zpět a opět síťové spojení zavře. To se stane při každém požadavku. Jiné protokoly umožňují otevřít spojení, přenést data, ponechat spojení otevřené, přenést zase nějaká data za chvilku – možná v závislosti na tom, jaká data jste přenesli předtím – a zavřít spojení až nakonec. Udržování otevřeného spojení stojí server nějakou práci. Jeden z běžných vzorů chování je, že po dobu, co je spojení otevřené, má klient konzistentní přístup k statickým datům na serveru. Pokud přichází velké množství souběžných požadavků, je udržení tohoto přístupu poměrně pracné. HTTP jsou obvykle krátkodobé, takže záruka neměnnosti a konzistence je podstatně snazší. Výsledkem je, že CouchDB může obsluhovat velké množství souběžných požadavků.

Dalším důvodem, proč CouchDB používá MVCC, je, že tento model je koncepčně (i programátorsky) snadný. CouchDB tedy používá míň kódu, a méně kódu znamená méně možných chyb, protože počet chyb na řádky kódu je konstantní.

Systém revizí je rovněž výhodný pro replikace a ukládání, ale o tom si povíme víc v dalších částech knihy.

Pojmy verze a revize vám mohou znít povědomě (pokud programujete a nepoužíváte verzovací systém, tak ihned přestaňte číst a jděte se nějaký populární verzovací systém naučit). Použití nových verzí pro změny v dokumentech připomíná správu verzí v VCS, ale je tu jeden důležitý rozdíl: CouchDB nikde negarantuje, že bude starší verze uchovávat.

Dokumenty podrobněji

Podívejme se na vytváření dokumentů podrobněji, pomocí curl -v, podobně jako jsme se dívali na vytváření databází. Zároveň si vytvoříme pár dokumentů, s nimiž budeme dál pracovat.

Přidáme si pár dalších desek. Vezmeme čerstvé UUID z adresy /_uuids. Pokud si nepamatujete, jak to funguje, koukněte se výš.

curl -vX PUT http://127.0.0.1:5984/albums/70b50bfa0a4b3aed1f8aff9e92dc16a0 -d '{"title":"Blackened Sky","artist":"Biffy Clyro","year":2002}'

Mimochodem, pokud byste chtěli ukládat víc informací, nerozpakujte se a přidejte je tam. A nestarejte se o to, že u některých alb neznáte všechny informace; prostě je tam nedáte. Bezschémové databáze jako CouchDB dokáží uložit dokumenty, co obsahují cokoli, co chcete. Nezapomínejte: měli byste relaxovat, a ne starat se o to, jestli máte všechna data, co vyžaduje schéma.

S přepínačem -v odpovídá CouchDB takto (pouze důležité části):

> PUT /albums/70b50bfa0a4b3aed1f8aff9e92dc16a0 HTTP/1.1
>
< HTTP/1.1 201 Created
< Location: http://127.0.0.1:5984/albums/70b50bfa0a4b3aed1f8aff9e92dc16a0
< Etag: "1-2248288203"
<
{"ok":true,"id":"70b50bfa0a4b3aed1f8aff9e92dc16a0","rev":"1-2248288203"}

Dostali jsme zpět status 201 Created, tedy totéž, co jsme viděli při vytváření databází. Hlavička Location obsahuje úplné URL k nově vytvořenému dokumentu. Máme tu i novou hlavičku Etag. V řeči HTTP označuje specifickou verzi daného zdroje (resource). V tomto případě označuje specifickou verzi (první) našeho nového dokumentu. Zní vám to povědomě? Ano, koncepčně je Etag totéž co číslo revize, a nemělo by být překvapením, že CouchDB použije na místě Etag právě interní číslo revize. Etag je užitečný pro cache. Podrobnosti o fungování nás čekají v Kapitole 8.

Přílohy

Dokumenty v CouchDB mohou mít přílohy podobně jako třeba e-maily. Příloha je identifikována jménem a obsahuje MIME typ (neboli Content-Type) a počet bajtů, které jsou v příloze uložené. Příloha mohou být jakákoli data. Nahlížejme na ně jako na soubory, přiložené k dokumentu. Těmito soubory mohou být texty, obrázky, dokumenty ve Wordu, hudba, video, …

Přílohy mají svá vlastní URL, na něž můžete data poslat. Řekněme, že chceme nahrát obrázek obalu CD k dokumentu 6e1295ed6c29495e54cc05947f18c8af (“There is Nothing Left to Lose”), a dejme tomu, že obrázek je uložen v souboru artwork.jpg v aktuálním adresáři:

> curl -vX PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/ artwork.jpg?rev=2-2739352689 --data-binary @artwork.jpg -H "Content-Type: image/jpg"

Volba -d@ říká curl, aby poslal obsah souboru v těle HTTP dotazu. Pomocí volby  -H řekneme CouchDB, že nahráváme soubor s typem JPEG. CouchDB si tuhle informaci uloží a pošle správnou hlavičku pokaždé, když bude posílat tuto přílohu. V případě obrázků, jako zde, zobrazí prohlížeč tento obrázek, namísto toho, aby nabídl data ke stažení. Později uvidíme, jak šikovná vlastnost to je. Všimněte si, že musíte zadat číslo aktuální revize dokumentu, k němuž přílohu připojujeme, stejně jako když aktualizujeme dokument samotný. Protože konec konců přidání přílohy je změna dokumentu.

Pokud do prohlížeče zadáte http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af/artwork.jpg, měli byste vidět nahraný obrázek.

Pokud si opět přečtete dokument, uvidíte novou položku:

curl http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af

CouchDB vrací:

{"_id":"6e1295ed6c29495e54cc05947f18c8af","_rev":"3-131533518","title": "There is Nothing Left to Lose","artist":"Foo Fighters","year":"1997","_attachments":{"artwork.jpg":{"stub":true,"content_type":"image/jpg","length":52450}}}

_attachments je seznam klíčů a hodnot, kde hodnoty jsou JSON objekty, které obsahují metadata k příloze. Hodnota stub=true nám oznamuje, že databáze vrátila pouze metadata. Když použijeme v URL volbu ?attachments=true, dostaneme v objektu řetězec v kódování Base64, který obsahuje binární data dané přílohy.

Na další volby se podíváme později, jak budeme probírat další funkce CouchDB, jako je např. replikace, kterou si popíšeme právě teď.

Replikace

Replikace jsou v CouchDB mechanismem, kterým synchronizujeme obsah databází. Podobně jako rsync synchronizuje dva adresáře (lokálně nebo přes síť), replikace synchronizuje dvě databáze.

V jednoduchém požadavku POST řeknete CouchDB zdroj a cíl replikace. CouchDB si zjistí, jaké dokumenty a nové revize jsou ve zdrojové databázi a v cílové ne, a začne přenášet chybějící dokumenty a revize.

Mechanismus replikací si popíšeme později, v této kapitole se podíváme jen na to, jak ho používat.

Nejprve si vytvoříme cílovou databázi. Při replikaci se cílová databáze nevytváří automaticky, a pokud neexistuje, vrátí požadavek na replikaci chybu.

curl -X PUT http://127.0.0.1:5984/albums-replica

Teď použijeme databázi albums-replica jako cílovou:

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"albums","target":"albums-replica"}'

Od verze 0.11 umožňuje CouchDB použít volbu "create_target":true v JSON poslaném na adresu _replicate. jak název napovídá, vytvoří cílovou databázi, pokud neexistuje.

CouchDB odpoví (kvůli čitelnosti si výstup naformátujeme):

{
  "history": [
    {
      "start_last_seq": 0,
      "missing_found": 2,
      "docs_read": 2,
      "end_last_seq": 5,
      "missing_checked": 2,
      "docs_written": 2,
      "doc_write_failures": 0,
      "end_time": "Sat, 11 Jul 2009 17:36:21 GMT",
      "start_time": "Sat, 11 Jul 2009 17:36:20 GMT"
    }
  ],
  "source_last_seq": 5,
  "session_id": "924e75e914392343de89c99d29d06671",
  "ok": true
}

CouchDB si udržuje session history replikací. Odpověď na požadavek replikace obsahuje historii tohoto replikačního sezení. Je na místě si všimnout i toho, že požadavek na replikaci zůstává otevřený, dokud replikace nedoběhne. Pokud máte spoustu dokumentů, bude to nějakou dobu trvat, a vy nedostanete žádnou odpověď, dokud akce neproběhne. Je důležité poznamenat, že replikace posílá dokumenty v takové podobě, v jaké byly na začátku replikace. To znamená, že jakékoli úpravy, vykonané po startu replikace, nebude replikováno.

Na konci dostaneme "ok": true  – pokud vše proběhlo dobře. Když se teď podíváte do databáze albums-replica, uvidíte dokumenty, co jsme předtím vytvořili v databázi albums. Skvělé, že?

To, co jsme právě udělali, se v terminologii CouchDB nazývá lokální replikace. Vytvořili jsme lokální kopii databáze. To se hodí při zálohování nebo při vytváření snapshotů určitého stavu „na později“. Můžete to využít při vývoji aplikace, když chcete mít možnost se snadno vrátit k určitému stavu dat.

Je víc typů replikací, které jsou užitečné v dalších situacích. Položky source a target v požadavku na replikaci jsou vlastně odkazy (jako v HTML), takže tvar, který jsme zadali, byl relativní k serveru, s nímž pracujeme (tedy localhost). Můžeme zadat vzdálenou adresu:

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"albums","target":"http://127.0.0.1:5984/albums-replica"}'

Použití lokálního zdroje a vzdáleného cíle se nazývá push replikace. Tlačíme (push) změny na vzdálený server.

Protože nemáme druhý CouchDB server po ruce, použili jsme kompletní adresu našeho místního serveru, ale určitě budete schopni odvodit, jak zapíšete libovolný vzdálený server.

Tímto způsobem můžeme svoje místní změny sdílet se vzdálenými servery.

Můžeme použít vzdálený zdroj a místní cíl a udělat tak pull replikaci. Taková replikace je užitečná ve chvíli, kdy chcete získat změny ze vzdáleného serveru, které provedl někdo jiný:

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"http://127.0.0.1:5984/albums-replica","target":"albums"}'

No a konečně můžete spustit vzdálenou replikaci, což se hodí při vzdálené správě databází:

curl -vX POST http://127.0.0.1:5984/_replicate -d '{"source":"http://127.0.0.1:5984/albums","target":"http://127.0.0.1:5984/albums-replica"}'

CouchDB a REST

CouchDB se pyšní tím, že má RESTful API, ale tyto replikace trénovanému oku nebudou připadat moc RESTy. Co s tím? Zatímco jádro CouchDB API pro databáze, dokumenty a přílohy je RESTfull, neplatí to pro všechna API. Příkladem je právě API replikací. Je jich víc, jak uvidíte v dalších kapitolách.

Proč tu mícháme RESTful a neRESTful API dohromady? Jsou snad vývojáři příliš líní na to, aby použili REST všude? Pamatujeme, REST je architektonický styl, který se perfektně hodí na některé architektury (jako je třeba API dokumentů v CouchDB). Ale není to univerzální recept na vše. Spouštění událostí, jako jsou právě replikace, nedává ve světě REST moc smysl. Je to spíš jako tradiční volání procedury. A není na tom nic špatného.

Věříme ve filosofii „použij pro daný úkol správný nástroj“, a víme, že REST se nehodí pro vše. Odkazujeme na Leonarda Richardsona a Sama Rubyho, kteří svůj pohled na problematiku popsali v knize RESTful Web Services (O’Reilly).

Shrnutí

Stále jsme nepopsali komplentí CouchDB API, ale probrali jsme velmi podrobně nejzákladnější části. Další si doplníme postupně. Pro tuto chvíli jste připraveni začít psát CouchDB aplikace.

Tento text je součástí překladu knihy CouchDB: The Definitive Guide. Stejně jako autoři originálu oceníme věcné připomínky a pomoc s textem, za které předem děkujeme.

Komentáře

Subscribe
Upozornit na
guest
5 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
J.A.V.

S verzí CouchDB 1.0.1 na FC14 nefunguje uvedený příklad replikace – chybí mu content type. Stačí jen doplnit -H „Content-Type: application/json“ na konec příkazu.

Lolek

A už to podporuje více než jednoho uživatele?

Ivo

Po zadání:
curl -X PUT http://127.0.0.1:5984/albums/6e1295ed6c29495e54cc05947f18c8af -d ‚{„title“:“There is Nothing Left to Lose“,“artist“:“Foo Fighters“}‘

z příkladu to vypisuje:
{„error“:“bad_r­equest“,“reason“:“in­valid UTF-8 JSON“}

Chová se to tak jak přes curl, tak přes REST Client for Firefox.

Nenapadá Vás něco? Progooglil jsem celý web a našel jsem jen opravy chybějících čárek, apostrofů a podobně. Přehlédl jsem něco?

Díky, Ivo

J.A.V.

A jaký OS? Příkazový řádek ve Windows má problémy s parsováním uvozovek. Viz tohle: http://stackoverflow.com/questions/3347974/curl-giving-invalid-utf-8-json-error-from-couchdb-although-json-is-fine-any-id/3353174#3353174

Měl jsem stejný problém, tak jsem se s experimenty vrátil na FC14, kde ale zase popadá polovina self-testů couchDB.

vixh

Prikaz curl -vX POST http://127.0.0.1:5984/_replicate -d ‚{„source“:“al­bums“,“target“:“al­bums-replica“}‘ vrati {„error“:“bad_c­ontent_type“,“re­ason“:“Content-Type must be application/json“}

dokud nepridate k nemu -H „Content-Type: application/json“

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.