17 мая 2011

Clojure, NoSql

Раз пошла такая пьянка, режь последний огурец. Я надеюсь Вас не смущает такое начало, тем более, что сегодня мы резко переместимся в сторону NoSQL. Почему резко? Да, потому что я только что впервые в жизни набрал в google "clojure NoSql", и этот пост пишу в режиме live.

После некоторых скитаний, оказываемся здесь: http://habrahabr.ru/blogs/nosql/77909/
Хм, ничего не понял. Будем как обычно основываться на интуиции. Итак couchDB или mongoDB? И тут ассоциативно: Erlang versus C++. А так как я знаю, что такое голосование долларом (рублём), то своим вниманием я голосую, конечно же против C++.
Erlang мне нравится, чрезвычайно интересный нишевый функциональный язык.


sudo apt-get install couchdb


http://127.0.0.1:5984/

Ага, работает.

Хорошо спрашиваем google "clojure couchdb". Ответил нам библиотекой [clojure-couchdb "0.4.5"]. Добавим ее в зависимости для проекта, выполним lein deps.

 Ну что же, давайте хранить сообщения блога теперь в couchdb. Для начала создадим базу данных. Сделаем это через clojure repl, в целях знакомства с clojre-couchdb api.


lein swank
emacs M+x slime-connect

Загрузим символы из couchdb.client


(use 'couchdb.client)


Какие у нас базы данных есть?


(database-list "http://localhost:5984/")


Создадим новую базу данных


(database-create "http://localhost:5984/" "blog")


Добавим туда документ


(document-create "http://localhost:5984/" "blog"  "post" {:title "New post" :body "My name is Michael. I live in Minsk. Minsk is the capital of Belarus."})

Фух, неплохо. На одном дыхании.

Небольшие технические подробности о couchDB. couchDB нереляционная документо-ориентированная база данных написанная на языке Erlang. API реализуется с помощью RESTful HTTP/JSON.

Управление документами осуществляется с помощью функций (document-* host database &optional id data)

Давайте получим обратно список документов:


(document-list "http://localhost:5984/" "blog")


Давайте получим содержимое документа:


(document-get "http://localhost:5984/" "blog" "post")

Давайте изменим текущий объект, по принципу "получить-смерджить-вставить":


(let [doc (document-get "http://localhost:5984/" "blog" "post")]
         (document-update "http://localhost:5984/" "blog" "post" (merge doc {:title "Not so new post"})))
 


Давайте удалим этот объект:


(document-delete "http://localhost:5984/" "blog" "post")

Всё что мне надо я узнал. Давайте внедрять. И на этом этапе шаблон model-view-pattern подходит нам как нельзя кстати, нам всего-то надо заменить модель.



Добавим адрес базы данных в файл src/clj_blog/system/db.clj


(def *couch-host* "http://127.0.0.1:5984/")
(def *couch-db* "post")


 Прежде чем перейти к модели, один подводный камень нас ожидает. Структура "таблицы", а точнее документа в couchDB будет слегка отличатся от структуры sql таблицы, поэтому нам необходимо будет изменить файлы шаблонов.

В файлах templates/posts/*.soy  нужно заменить все post.id на post._id
В файлах tempaltes/posts/*.soy нужно заменить textarea ... name ="text" на textarea ... name="body"


Создадим файл

src/clj_blog/models/m_couch_post.clj

следующего содержания




Меняем в контроллере использование m-post модели на m-couch-post


(:require [clj-blog.models.m-couch-post :as post]
  .....

Для просмотра базы данных можно просто использовать ссылку.

 http://127.0.0.1:5984/blog/

Размер исзодного кода модели уменьшился на 15%:) Это произошло засчет более простого API для работы с JSON документами, чем с SQL таблицами.


2 комментария:

  1. Спасибо было интересно. Вы можете порекомендовать какие-то ресурсы именно по nosql(couchdb) или можно читать любую книжку?

    ОтветитьУдалить
    Ответы
    1. Дальше хелловорлдов в носикле я не продвинулся, много делается на обычном сикле гораздо проще.

      Удалить