Python + CouchDB

Знайшов час і нарешті трохи погрався з однією з NoSQL баз даний CouchDB. Саме ця база з інших зацікавила мене тим, що вона написана на Erlang. Враховуючи що її прибрав до рук Apache певно вірять у велике майбутнє.

Архітектура системи

Подібно іншим документно-орієнтованим СУБД (Mnesia, Lotus Notes, MongoDB), і на відміну від реляційних БД, CouchDB призначена для роботи з напів-структурованою інформацією і має такі особливості:

  • Дані зберігаються не в рядках і колонках, а у вигляді JSON-подібних документів, моделлю яких є не таблиці, а дерева;
  • Типізація елементів даних, тобто зіставлення окремих полях документів типів INTEGER, DATE тощо, не підтримується – замість цього користувач повинен написати функцію-валідатор;
  • Цілісність бази даних забезпечується виключно на рівні окремих записів (але не на рівні зв’язків між ними);
  • Зв’язку між таблицями або записами принципово не підтримуються, відповідно операція об’єднання (JOIN) між таблицями не визначена;
  • Для побудови індексів і виконання запитів використовуються функції представлення (view);
  • Функції-валідатори, функції-подання, функції-фільтри зберігаються в текстовому вигляді в самій базі даних;
  • Ці функції, як правило, написані на мовах JavaScript або Erlang, а для їх виконання запускається окремий сервер запитів, взаємодія з яким відбувається за допомогою сокетів і текстового JSON-протоколу;
  • Кожній базі даних у системі CouchDB відповідає єдине B-дерево (не плутати з двійковим деревом);
  • Кожне B-дерево зберігається у вигляді окремого файлу на диску;
  • Одночасно може бути запущено декілька потоків для читання бази даних і лише один – для запису;
  • Цілісність бази даних забезпечується тільки при запису даних на диск;
  • Подання зберігаються в БД та їх індекси оновлюються безперервно, проте при кожному оновленні функцій подання або відображення оновлюється все B-дерево цілком;
  • При обробці даних за допомогою функцій-уявлень використовується спрощена модель технології MapReduce, що дозволяє проводити паралельні обчислення, в тому числі і на багатоядерні процесори;
  • Розподіл обчислень на кілька вузлів не підтримується – замість цього використовується механізм реплікації;
  • Обробка даних за допомогою ланцюжка послідовних функцій MapReduce не підтримується;
  • Підтримується вертикальна масштабованість, що означає підтримку не тільки величезних кластерів, але і портативних пристроїв (нетбуки, смартфони та ін);
  • Зовнішній інтерфейс (API) до даної СУБД побудований на основі архітектури REST, тобто сама база даних, окремі записи, відображення і запити – суть ресурси, які мають унікальну адресу (URL) і підтримують операції GET, PUT, POST, DELETE;
  • Тому для взаємодії з базою даних було написано так багато клієнтських бібліотек, у тому числі на таких мовах JavaScript, PHP, Ruby, Python і Erlang;
  • Взаємодія між окремими компонентами СУБД, тобто з серверами уявлень здійснюється знову ж таки за допомогою текстового протокол HTTP, а дані передаються в форматі JSON; це дозволило використовувати різні мови програмування для написання цих компонентів – Java, Python, JavaScript та ін.

Історія розвитку

Проект CouchDB був прийнятий в інкубатор Apache у лютому 2008 року. Не дивлячись на те, що CouchDB спочатку призначався для роботи в операційній системі Linux, вже розроблено варіанти цієї системи для операційних систем Windows і MacOS. Більш того, дистрибутив Linux Ubuntu 9.10 (Karmic Kola) по-замовчуванням включає CouchDB.

Використання CouchDB

Незважаючи на те, що реліз CouchDB має номер 0.10, вона вже використовується в багатьох програмних продуктах і на безлічі веб-сайтів, в тому числі:

  • UbuntuOne, Firefox, TomBoy, Akonadi, Evolution – для синхронізації адрес, заміток і закладок.
  • Ajatus – розподілена CRM-система.
  • Mozilla Raindrop – агрегатор повідомлень електронної пошти, соціальних мереж, систем обміну миттєвими повідомленнями (Skype, Jabber).

Інтерфейси на Python

По великому рахунку для керування цією базою цілком достатньо urllib2. Але вже є деякі готові обгортгки, які я спробував сам.

CouchDB має чудовий веб-інтерфейс до керування самою базою. Там можна створювати бази, робити вибірки та тестити javascript функції.

couchdb-python має всі корисні абстракції і навіть трохи більше. Це “більше” полягає в можливості поставити схему документа в декларативному Django-like стилі і реалізація пітонячьего view-сервера. Перше потрібно щоб якось структурувати документи і роботу з ними, а друга для того, щоб використовувати python як мову для map/reduce обробників замість штатного JavaScript. Вміє працювати як з simplejson так і з швидкою cjson бібліотекою. Використовує httplib2.

сouchdbkit – вміє практично все теж саме, але має трохи більше хелперів і екстеншенів. Вміє інтегруватись із Django. Тягне за собою в залежності restkit і розумну бібліотеку anyjson для вибору оптимального json пакету в системі. Недоліком є відсутність view-сервера.

couchquery – з усіх найменш відома та найслабша. Має базовий набір для роботи з сouchdb.

42-django-couchdb Це вже надбудова над couchdb-python у вигляді Django-бд бекенда.

couchdb-python


>>> import couchdb
>>> from couchdb.client import Server
>>> from couchdb.schema import Document, TextField, IntegerField
>>>
>>> server = Server('http://localhost:5984/')
>>> server.resource.http.add_credentials('admin', 'pass')
>>> db = server.create('db1')
>>>
>>> class Banner(Document):
...     clicks = IntegerField()
...     banner = TextField()
...
>>> b = Banner()
>>> b.clicks = 1
>>> b.banner = 'banner1'
>>> b.store(db)
<Banner u'8d97edb044111e1c7be5d1b0b36c5510'@
u'1-7fd3d19dabfbe52d71327711c6c6c3e0' 
{u'banner': u'banner1', u'clicks': 1}>
>>> b2 = Banner()
>>> b2.clicks=10
>>> b2.banner = 'banner2'
>>> b2.store(db)
<Banner u'5538aad62da4ba9d1ef18fd0f80991e3'@
u'1-e9ed885d4ad523d485b271e4a695f266' 
{u'banner': u'banner2', u'clicks': 10}>
>>> len(db)
2
>>> for id in db:
...     ban = Banner.load(db,id)
...     print ban.clicks,ban.banner
...
10 banner2
1 banner1
>>> sql = '''function(doc) { if (doc.banner=="banner2"){ 
emit([doc.banner], doc); }}'''
>>> for i in db.query(sql):
...     print i.value.get('clicks'),i.value.get('banner')
...
10 banner2

сouchdbkit
як імплантацію до Django прописуємо settings.py


#settings.py
COUCHDB_DATABASES = (
        ('engine.banners', 'http://admin:[email protected]:5984/db1'),
              )
INSTALLED_APPS = (
    ...
    'couchdbkit.ext.django',
    ...
)

модель виглядає наступним чином


#models.py
from couchdbkit.ext.django.schema import *
class Banner(Document):
    clicks = IntegerProperty()
    banner = StringProperty()

з javascript функціями напряму не працює, для початку треба створити view-ху у базі, після чого можна її викликати:


#views.py
from engine.banners.models import Banner
def some_view(request):
    b= Banner()
    banner = b.view('d1/v1').first()

можна працювати із формами по Django-ORM-у


#forms.py
 class BannerForm(DocumentForm):    
     class Meta:
         document = Banner

#views.py
 def some_form(request):
    if request.POST:
    form = BannerForm(request.POST)
    if form.is_valid():
        form.save()  
    else:
        form = BannerForm()

сouchdbkit непоганий, але ще трохи недопрацьований як на мене.

Цікаво було б почути хто що використовує та зауваження в мою сторону 🙂




coded by nessus