Obsługa bazy dokumentów CouchDB w Pythonie
17 February 2009
Comments
CouchDB to bezschematowa i nierelacyjna baza danych "dokumentów" napisana w Erlangu. Obecnie projekt znajduje się w fazie rozwojowej, lecz jest dość użyteczny i aktywnie rozwijany pod egidą Fundacji Apache. W ostatnich miesiącach coraz głośniej o tym projekcie na różnych konferencjach, jak i poprzez wykorzystanie CouchDB w nowych projektach. Oto krótka charakterystyka:
- Dostępna przez API REST (HTTP POST/PUT/GET/DELETE)
- Bezschematowa i nierelacyjna.
- Replikowalna
- Widoki o dużych możliwościach
- JSON na wejściu i wyjściu
- Napisana w Erlangu - współbieżnym języku programistycznym
Instalacja
Na wiki CouchDB znajdziemy sekcję dotyczącą instalacji CouchDB pod różnymi dystrybucjami i systemami operacyjnymi. Oprócz zainstalowania samej aplikacji należy zająć się wstępną konfiguracją czy skryptami startowymi (lecz tym powinny zająć się pakiety dla poszczególnych dystrybucji). Ja skorzystałem z ebuilda dla Gentoo i otrzymałem gotowy do pracy serwer baz danych. Istnieje także pakiet Pythona do obsługi tej bazy danych - couchdb-python, który możemy zainstalować poleceniem:easy_install CouchDB
Po zainstalowaniu CouchDB powinniśmy być w stanie uruchomić serwer baz danych (pod Gentoo /etc/init.d/couchdb start). Gdy serwer zostanie uruchomiony pod adresem http://localhost:5984/_utils/ powinien dostępny być panel CouchDB (odpowiednik phpmyadmin), za pomocą którego możemy zarządzać bazami danych.
Jak to działa
Dane trzymane są w postaci struktur JSON posiadających unikalne ID oraz numer rewizji. W przypadku zmiany wpisu nowa wersja jest dopisywana z nowym numerem rewizji. Stare rekordy istnieją aż do przeczyszczenia bazy danych ("Compact"). Celem dopisywania, a nie nadpisywania jest kontrola integralności, baza też nie pozwoli na aktualizacje jeżeli posługujemy się starszą rewizją. By pobrać określone rekordy w CouchDB stosuje się widoki (perspektywy) napisane w JavaScript stosujące Map/Reduce (choć można skorzystać z serwera widoków napisanego w innym języku!). Dane jakie widok zwraca generowane są przy jego pierwszym wywołaniu, tak więc kolejne wywołania od razu dostają przygotowane dane (choć istnieją widoki tymczasowe wykonywa za każdym razem). Jest to szczegółowo opisane w dokumentacji.Obsługa CouchDB z poziomu Pythona
couchdb-python dostarcza trzy biblioteki - serwer widoków dla funkcji napisanych w Pythonie, konwertera obiektów Pythona na struktury JSON (i na odwrót) oraz standardowego klienta do bazy danych. Dokumentację do couchdb-python znajdziemy w postaci Docstringów w plikach pakietu. Oto prosty przykład zastosowania klienta:from couchdb import *
server = Server('http://localhost:5984/')
# wybieramy istniejącą bazę
db = server['test01']
#lub tworzymy:
#db = server.create('test01')
# wyświetlamy rekord o id "1"
print db['1']
#dodajemy rekord
doc_id = db.create({'name': 'John', 'surname': 'Doe'})
# i go wyświetlamy
print db[doc_id]
# -*- coding: utf-8 -*-
from couchdb import *
from couchdb.schema import Document, TextField, IntegerField, DateTimeField
import datetime
# połączenie z serwerem
server = Server('http://localhost:5984/')
# tworzymy, bądź usuwamy/tworzymy bazę na fotki
try:
db = server.create('fotki')
except:
del server['fotki']
db = server.create('fotki')
class Fotka(Document):
name = TextField()
desc = TextField()
h = IntegerField()
w = IntegerField()
added = DateTimeField(default=datetime.datetime.now())
# dodajemy kilka fotek
f = Fotka(name='Moje foto rodzinne', desc='ciekawa fota', h = 100, w = 200)
f.store(db)
f = Fotka(name='Ja i zdzisiek', desc='no comments', h = 200, w = 300)
f.store(db)
f = Fotka(name='Tapeta01', desc='wyjechana tapeta', h = 1200, w = 1300)
f.store(db)
# pobieramy wszystkie fotki
for uuid in db:
print Fotka.load(db, uuid)
# wykonujemy zapytanie za pomocą widoku tymczasowego
print
code = "function(d) { if (d.h > 1000 ) emit(d.name,null); }"
result = db.query(code)
for res in result:
print res.key
{'_id': '_design/fotki', 'language': 'javascript', "views": KOD}
Gdzie wartość pola _id musi zaczynać się od _design/ i kończyć nazwą grupy widoków. Wartość klucza views to kod widoków, np:
{
"all": {
"map": "function(doc) { emit(null, doc) }"
},
"by_height": {
"map": "function(doc) { emit(doc.h, doc) }"
},
"tapety": {
"map": "function(doc) { if (doc.h > 1000) emit(doc.h, doc) }",
}
}
from couchdb.design import ViewDefinition
...
# dodajemy trwały widok
print
tapety = ViewDefinition('fotki', 'tapety',
'function(doc) { if (doc.h > 1000) emit(doc.h, doc) }')
ViewDefinition.sync_many(db, [tapety, ])
# wywołujemy
for res in db.view('fotki/tapety'):
print res.value
W Sieci
Obsługa CouchDB z poziomu JavaScriptPrezencja o CouchDB - PDF, Polska
Using CouchDB with Django
RkBlog
Comment article