Содержание


Вторая волна разработки Java-приложений

Работа с CouchDB через интерфейсы REST при помощи RESTClient в Groovy

Использование технологии REST и документ-ориентированной СУБД

Comments

Серия контента:

Этот контент является частью # из серии # статей: Вторая волна разработки Java-приложений

Следите за выходом новых статей этой серии.

Этот контент является частью серии:Вторая волна разработки Java-приложений

Следите за выходом новых статей этой серии.

Развить навыки по этой теме

Этот материал — часть knowledge path для развития ваших навыков. Смотри Использование NoSQL для анализа данных большого объема

В предыдущих статьях этой серии рассматривались платформы облачных вычислений, предоставляемые компаниями Google и Amazon. Несмотря на различия в реализации, обе платформы позволяют быстро разворачивать приложения и обеспечивают их масштабируемость. Более того, они также предоставляют беспрецедентные возможности по сборке, тестированию, эксплуатации и поддержке Java-приложений, причем без существенных затрат времени и средств. Однако облачные технологии являются не единственным фактором, определяющим прогресс в создании приложений на Java. Кроме них важную роль в ускорении процесса разработки играет доступность бесплатных решений, позволяющих сократить объем требуемого кода. К счастью, времена, когда приходилось писать собственные библиотеки объектно-реляционного отображения (ORM), журналирования и тестирования, остались в прошлом. Все эти задачи теперь решаются разнообразными свободно распространяемыми библиотеками, использование которых практически всегда предпочтительнее написания собственного кода.

Постоянно расширяющееся многообразие открытых технологий облегчает создание любых Java-приложений из готовых компонентов. Одной из таких технологий является новая СУБД Apache CouchDB (на момент написания этой статьи последней версией CouncDB была 0.10.0). После установки и запуска этой СУБД у вас не возникнет никаких сложностей с ее освоением. Все, что вам нужно для начала работы – это HTTP-соединение. Вам не потребуется ни JDBC-драйвер, ни дополнительное решение для администрирования. В этой статье приводится введение в CouchDB, а также рассказывается о том, как максимально быстро начать ее использовать. В целях упрощения установки мы будем использовать платформу Amazon EC2, а для взаимодействия с CouchDB – удобную библиотеку, написанную на Groovy.

Документ-ориентированная СУБД

В настоящее время реляционные СУБД занимают лидирующие позиции на рынке баз данных. Тем не менее, периодически возникают ситуации, в которых имеет смысл использовать объектно-ориентированные или документ-ориентированные СУБД, которые радикально отличаются от реляционных. CouchDB является представителем последнего типа. В ней нет схем, но она позволяет хранить документы в формате JSON (JavaScript Object Notation).

Представьте себе извещение о неправильной парковке. Этот клочок бумаги содержит ряд элементов, в частности, следующие:

  • дату нарушения;
  • время нарушения;
  • место, где произошло нарушение;
  • описание автомобиля;
  • регистрационный номер автомобиля;
  • описание нарушения.

Формат, а также сами данные, представленные в извещении, зависят от административного округа, в котором произошло нарушение. Более того, они могут меняться даже в пределах одного округа. Например, офицер, заполнявший извещение, мог забыть вписать точное время либо модель и марку автомобиля, указав лишь его регистрационный номер. Местоположение может быть указано в виде пересечения улиц (например, "На пересечении Четвертой улицы и Лексингтон") или в виде точного адреса (например, "19993 Мейн-стрит"). Однако семантика данных остается примерно одной и той же.

Содержимое извещений можно хранить в реляционной базе данных, однако может возникнуть ряд мелких трудностей. Например, как эффективно хранить местоположения, заданные в виде пересечения улиц? Если хранить названия обеих улиц в отдельных колонках, то как сохранять извещения, в которых вторая улица не указана? Должна ли база данных разрешать пустые значения в колонках?

Подобные проблемы возникают из-за чрезмерного уровня абстрагирования реляционной модели данных. В нашем случае вся информация уже находится в виде некоторого документа (извещения). Почему бы не хранить ее в виде документа, который хотя и не укладывается в строгую реляционную структуру, но зато имеет определенную высокоуровневую семантику. Именно это позволяет делать CouchDB. Эта СУБД предоставляет гибкие возможности описания подобных объектов данных и их хранения в виде документов, которые не имеют строгой схемы, но зато семантически схожи с другими документами.

CouchDB предоставляет возможности для поиска самих документов, их атрибутов, а также связывания документов подобно записям в реляционной базе данных. Эти действия выполняются при помощи представлений, а не операторов SQL. Представления фактически являются функциями, написанными пользователем на JavaScript в стиле MapReduce (т.е. необходимы функции отображения и сведения). Эти функции затем используются совместно для извлечения данных из документов, а также эффективного использования связей между документами. Более того, CouchDB достаточно интеллектуальна, чтобы вызывать функции только один раз для документов, остающихся неизменными в процессе обработки, что способствует высокой производительности.

Особый интерес представляет архитектура CouchDB, в которой воплощены в жизнь фундаментальные и чрезвычайно удачные концепции Web. Эта СУБД предоставляет API, следующие принципам REST, для создания, выборки, изменения и удаления документов, представлений и баз данных. Это существенно облегчает работу с СУБД, поскольку вам не потребуются ни драйверы, ни другие библиотеки для начала ее использования (достаточно лишь Web-браузера). Разумеется, существует ряд библиотек, облегчающих работу с CouchDB, однако они всего лишь используют сервисы REST через HTTP.

Аналогично самой всемирной паутине, CouchDB проектировалась с учетом необходимости масштабирования. Она написана на Erlang – языке параллельного программирования, специально предназначенном для создания распределенных, отказоустойчивых, непрерывно работающих приложений (см. раздел Ресурсы). Этот язык, доступный бесплатно всем желающим, был разработан компанией Ericson и широко используется в телекоммуникационных системах.

Установка CouchDB в лучших традициях облачных приложений

Процесс установки CouchDB зависит от вашей операционной системы. Если вы работаете с Windows® то вам понадобится Cygwin, компилятор Microsoft C и ряд других библиотек. В случае Mac необходимо использовать Macports. Если же у вас установлена одна из систем семейства Linux®, например, Ubuntu, то инсталляция CouchDB упрощается до предела. Однако не у всех под рукой есть Ubuntu. Или уже у всех?

Конечно у всех! Amazon EC2 представляет собой относительно недорогой способ использовать Ubuntu при необходимости. Итак, немного волшебства EC2, и вы сможете запустить собственный сервер CouchDB, а также остановить его после окончания работы.

Вначале следует найти экземпляр EC2 (AMI), который будет выступать в качестве виртуальной машины. В итоге я остановился на AMI ami-ccf615a5 c операционной системой Ubuntu 9.04, которая была новейшей версией на момент написания статьи (после опубликования статьи, наверное, будет доступен новый AMI с Ubuntu 9.10). Запустите экземпляр ami-ccf615a5 через Eclipse или консоль администрирования AWS. При этом не забудьте установить политику безопасности, разрешающую доступ через SSH (CouchDB использует HTTP, но для простоты мы будем настраивать ее через SSH-туннель). Для подключения к AMI вам потребуется пара ключей. Информация об их получении приведена в предыдущих статьях этой серии: Аренда сервера EC2 и EC2 - это просто.

После запуска экземпляра EC2 с Ubuntu 9.04 подключитесь к нему через ssh (не забывайте, что процесс запуска AMI может занимать около минуты). Пример подключения через окно консоли приведен ниже.

aglover#> ssh -i .ec2/agkey.pem root@ec2-174-129-157-167.compute-1.amazonaws.com

В моем случае AMI имеет DNS-имя ec2-174-129-157-167.compute-1.amazonaws.com, а пара ключей – agkey. У вас имена должны быть другими.

Откройте командный интерпретатор на виртуальной машине Ubuntu и выполните следующую команду:

apt-get update

А затем еще одну:

aptitude install couchdb

Эти команды автоматически установят CouchDB, однако она может оказаться не самой последней версии. Если вам требуется последняя версия, то следует собрать CouchDB из исходного кода (см. раздел Ресурсы).

После завершения выполнения второй команды следует убедиться, что сервер CouchDB запущен, выполнив команду ps -eaf. Вы можете перенаправить вывод ps утилите egrep для поиска процессов, имя которых заканчивается на couchdb. Результат должен выглядеть примерно так, как показано в листинге 1.

Листинг 1. Запущенные процессы CouchDB (переводы строк добавлены для удобства форматирования)
couchdb   1820     1  0 00:54 ?        00:00:00 /bin/sh -e /usr/bin/couchdb 
   -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb   1827  1820  0 00:54 ?        00:00:00 /bin/sh -e /usr/bin/couchdb 
   -c /etc/couchdb/couch.ini -b -r 5 -p /var/run/couchdb.pid -o /
couchdb   1828  1827  0 00:54 ?        00:00:00 /usr/lib/erlang/erts-5.6.5/bin/beam 
   -Bd -- -root /usr/lib/erlang -progname erl -- -home /v
couchdb   1836  1828  0 00:54 ?        00:00:00 heart -pid 1828 -ht 11

Далее вернитесь на свой компьютер и настройте SSH-туннель для подключения к экземпляру CouchDB, как если бы он выполнялся локально. Для этого откройте окно командной строки и выполните следующую команду:

ssh -i ваш ключ -L 5498:localhost:5984 root@DNS-имя вашего AMI

Наконец, откройте браузер на локальном компьютере и обратитесь по адресу http://127.0.0.1:5498/. В результате вы должны увидеть приветственное сообщение в формате JSON, как показано ниже.

{"couchdb":"Welcome","version":"0.8.0-incubating"}

Итак, теперь все готово, и наступило время проверить возможности CouchDB.

Использование сервисов REST при помощи RESTClient в GroovyRESTClient

Как вы уже заметили, работа с CouchDB значительно облегчается благодаря тому, что она предоставляет доступ к данным через API в стиле REST. Таким образом, практически любые операции с данными могут быть выполнены через протокол HTTP.

Существует множество библиотек и приложений для взаимодействия по HTTP. В случае если взаимодействие осуществляется с сервисами REST, я, как правило, предпочитаю Groovy-библиотеку RESTClient, представляющую собой расширение HTTPBuilder (см. раздел Ресурсы). HTTPBuilder, который в свою очередь является надстройкой над популярным Apache-проектом HTTPClient, адаптирует синтаксис запросов POST, GET, PUT и DELETE для Groovy. Эта библиотека сама написана на Groovy, поэтому с ее помощью очень легко писать скрипты для обращения к ресурсам REST, в частности, для взаимодействия с CouchDB.

Проще и быстрее вместе с Grape

Далее мы продолжим использовать преимущества второй волны Java-разработки, позволяющие легко и быстро использовать бесплатные (или дешевые) технологии. Одной из таких технологий является Grape (Groovy Advanced Packaging Engine или Groovy Adaptable Packaging Engine), которая особенно полезна при работе с такой библиотекой, как HTTPBuilder (см. раздел Ресурсы). Grape – это менеджер зависимостей, позволяющий скриптам и классам Groovy автоматически конфигурировать свои зависимости на этапе выполнения. Это облегчает использование различных открытых библиотек, поскольку вам не придется загружать ряд JAR-файлов перед началом разработки. Например, благодаря Grape вы можете написать скрипт на Groovy, который будет использовать HTTPBuilder, не имея под рукой JAR с самим HTTPBuilder. Подобные зависимости будут загружены через Apache Ivy на этапе выполнения или компиляции.

Grape можно задействовать при помощи аннотаций и вызовов методов. Например, вы можете пометить определенный метод или класс аннотацией @Grab. Она представляет собой метаданные, определяющие некоторую зависимость (при этом Ivy позволяет автоматически определить все косвенные зависимости). На этапе выполнения (или компиляции, если она предшествует выполнению) Grape загрузит все указанные зависимости и поместит их в classpath. При этом Grape проверяет наличие нужных JAR-файлов в classpath, даже если библиотеки были ранее загружены.

Работа с CouchDB через REST при помощи Groovy

Перед созданием любых документов в CouchDB необходимо создать саму базу данных. Для создания базы данных извещений о неправильной парковке выполните HTTP-запрос типа PUT при помощи RESTClient и предметно-ориентированного языка HTTPBuilder (DSL), как показано в листинге 2. Весь исходный код примеров на Groovy доступен по ссылке, приведенной в разделе Загрузка).

Листинг 2. Создание базы данных CouchDB
import static groovyx.net.http.ContentType.JSON
import groovyx.net.http.RESTClient

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', 
   version='0.5.0-RC2')
def getRESTClient(){
  return new RESTClient("http://localhost:5498/")
}

def client = getRESTClient()
def response = client.put(path: "parking_tickets",
        requestContentType: JSON, contentType: JSON)

assert response.data.ok == true : "response from server wasn't ok"

В ответ CouchDB должна вернуть строку {"ok":true}. Как видно из листинга 2, HTTPBuilder позволяет легко проанализировать строку в формате JSON и убедиться, что значением элемента ok является true.

Далее пришло время создать несколько документов, представляющих собой извещения о неправильной парковке. При моделировании этих документов необходимо учитывать ряд аспектов, связанных с извещениями. В частности, не забывайте, что эти извещения являются отражением реальных бланков, заполняемых блюстителями порядка, т.е. некоторые поля могут быть не заполнены или нарушать установленный формат (вспомните ситуацию с пересечением улиц и точными адресами).

Используя HTTPBuilder, вы можете создавать документы в CouchDB при помощи HTTP-запросов типа PUT (аналогичный запрос использовался в листинге 2 для создания базы данных). При этом необходимо следовать формату типа "имя-значение", принятому в JSON, поскольку CouchDB работает с документами JSON. Для этого вы можете использовать структуру данных в Groovy, напоминающую ассоциативный массив, которую HTTPBuilder самостоятельно преобразует в формат JSON. Пример приведен в листинге 3.

Листинг 3. Создание документа в базе данных CouchDB при помощи RESTClient
response = client.put(path: "parking_tickets/1234334325", contentType: JSON,
        requestContentType:  JSON,
        body: [officer: "Kristen Ree",
                location: "199 Baldwin Dr",
                vehicle_plate: "Maryland 77777",
                offense: "Parked in no parking zone",
                date: "2009/01/31"])

assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "1234334325" : "the returned ID didn't match"

В листинге 3 необходимо обратить внимание на ряд следующих моментов. Во-первых, при выполнении запроса типа PUT к документу CouchDB необходимо указать UUID. Вы можете самостоятельно присваивать эти идентификаторы документам либо оставить это на усмотрение CouchDB. В листинге 3 в качестве идентификатора указана строка "1234334325", которая добавляется в конец URL запроса. Если этот UUID свободен, то он будет присвоен созданному документу. Во-вторых, обратите внимание на элемент body в запросе, в котором содержится список пар типа "имя-значение" как в обычном ассоциативном массиве. Например, в качестве имени офицера указано Kristen Ree, а места - 199 Baldwin Dr.

В листинге 4 показан еще один пример добавления документа-извещения в базу данных CouchDB.

Листинг 4. Пример создания еще одного документа-извещения
def id = new Date().time
response = client.put(path: "parking_tickets/${id}", contentType: JSON,
        requestContentType:  JSON,
        body: [officer: "Anthony Richards",
                location: "Walmart Parking lot",
                vehicle_plate: "Delaware 4433-OP",
                offense: "Parked in non-parking space",
                date: "2009/02/01"])


assert response.data.ok == true : "response from server wasn't ok"
assert response.data.id == "${id}" : "the returned ID didn't match"

После выполнения каждого PUT-запроса через RESTClient следует убедиться, что в JSON-отклике сервера элемент ok имеет значение id, а также присутствует корректный идентификатор документа. Обратите внимание, что в листинге 4 в качестве UUID документа используется текущее время. Этот подход, хотя и не гарантирует отсутствие дубликатов, вполне допустим в простых ситуациях.

После успешного создания нового документа в базе данных сервер возвращает фрагмент JSON, содержащий UUID документа и идентификатор ревизии. Ниже показан фрагмент JSON, который проверяется в листинге 4.

{"ok":true,"id":"12339892938945","rev":"12351463"}

Если вы самостоятельно выполните этот пример, то, несомненно, получите другие значения элементов id и rev. Учтите, что к значению id можно получить доступ при помощи выражения response.data.id.

Изменения документов в CouchDB отслеживаются при помощи ревизий. Они позволяют откатываться на предыдущие ревизии документов по их идентификаторам аналогично тому, как это работает в системах CVS и Subversion.

Представления в CouchDB

Теперь, когда мы создали несколько парковочных извещений (или документов в CouchDB), пришло время добавить представление. Не забывайте, что представления являются не более чем функциями MapReduce, написание которых ложится на плечи разработчика. Однако во многих случаях вам не потребуется функция reduce, поскольку большую часть действий можно выполнить в функции отображения (map). Она делает именно то, что следует из ее названия, т.е. отображает те элементы данных, с которыми следует выполнить определенные действия, например, найти или отфильтровать.

Пока у нас есть два извещения: одно выдано офицером Ри (Ree), а второе - офицером Ричардсом (Richards). Например, для того чтобы найти все извещения, выданные Ри, достаточно написать функцию map, фильтрующую документы по значению атрибута officer. Полученные результаты затем должны быть переданы встроенной функции emit.

Futon: интерфейс администрирования CouchDB

Представления можно создавать либо через API REST, предоставляемые CouchDB, либо через интерфейс администрирования под названием Futon. Он является не чем иным, как Web-приложением, доступным по адресу http://localhost:5498/_utils/. Если вы создали базу данных и документы, как показано выше, обратитесь по этому адресу, и вы должны увидеть страницу с простым интерфейсом для работы с базой данных parking_tickets. Страница показана на рисунке 1.

Рисунок 1. Страница интерфейса Futon
Futon interface screenshot
Futon interface screenshot

Выбрав базу данных parking_tickets, вы должны увидеть справа выпадающий список с названием Select view: (выбрать представление). Далее вы можете начать создавать представление, выбрав пункт Custom query... (произвольный запрос), как показано на рисунке 2.

Рисунок 2. Интерфейс для выбора представлений в Futon
Futon's view-selection interface screenshot
Futon's view-selection interface screenshot

Далее Futon перенаправит вас на страницу, на которой можно описать функции map и reduce, предварительно кликнув по ссылке View code (просмотреть код). Скопируйте код, приведенный в листинге 5, в текстовое поле Map.

Листинг 5. Пример простой функции map в CouchDB
function(doc) {
  if(doc.officer == "Kristen Ree"){
    emit(null, doc);
  }
}

Как видно из листинга 5, функция map написана на JavaScript. Ее действия заключаются в фильтрации документов в базе данных CouchDB по значению свойства officer. В частности, функция передает документ в функцию emit только в том случае, если именем офицера является Kristen Ree. Пример создания этой функции в Futon показан на рисунке 3.

Рисунок 3. Создание функции MapReduce
futon
futon

Далее вам потребуется ввести архитектурное имя документа (введите by_name) и имя представления (officer_ree). Эти имена будут использовать для формирования URL для последующего вызова представления. В данном случае URL будет выглядеть, как http://localhost:5498/parking_tickets/_view/by_name/officer_ree.

Теперь вы можете обращаться к этому представлению через HTTPBuilder, как показано в листинге 6.

Листинг 6. Запрос к представлению
response = client.get(path: "parking_tickets/_view/by_name/officer_ree", 
        contentType: JSON,  requestContentType:  JSON)

assert response.data.total_rows == 1

response.data.rows.each{
   assert it.value.officer == "Kristen Ree"
}

На данный момент представление вернет фрагмент JSON, содержащий единственный документ: извещение, выданное офицером Ree 31-го января. Объект response в листинге 6 скрывает детали HTTP-запроса и самостоятельно разбирает фрагмент JSON. Сам фрагмент можно увидеть, вызвав метод toString у свойства data объекта response. Результат выглядит подобно фрагменту, показанному в листинге 7.

Листинг 7. Результаты, возвращенные представлением
{"total_rows":1,"offset":0,"rows":[
  {"id":"1234334325","key":null,
   "value":{"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree",
       "location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
       "offense":"Parked in no parking zone","date":"2009/01/31"}}]}

Как вы можете убедиться, просмотрев фрагмент JSON, способность HTTPBuilder разбирать JSON оказывается весьма кстати, поскольку это позволяет легко обращаться к значениям различных атрибутов при помощи методов, аналогичных обходу графов.

Далее мы добавим еще несколько документов в базу данных для демонстрации возможностей CouchDB. Если вы хотите продолжать выполнять примеры, то произведите те же действия (код можно найти по ссылке в разделе Загрузка).

Встроенная функция emit служит для обработки результатов отображения. Если не установить никаких ограничений в функции map (подобно показанным в листинге 5), emit просто отсортирует переданные ей документы. Например, если вам требуется получить все извещения в порядке их выдачи, то вы можете просто передать их emit, указав поле date (в SQL для подобных целей служит блок ORDER BY). Пример приведен в листинге 8.

Листинг 8. Пример простейшей функции map
function(doc) {
  emit(doc.date, doc);
}

В листинге 9 показан HTTP-запрос типа GET к этому представлению, в котором указано архитектурное имя (dates) и имя самого представления (by_date).

Листинг 9. Пример запроса к представлению
response = client.get(path: "parking_tickets/_view/dates/by_date", contentType: JSON,
        requestContentType:  JSON)
assert response.data.total_rows == 4

Запрос, показанный в листинге 9, возвращает все документы в базе данных parking_tickets, отсортированные по дате. Оператор assert проверяет, что значение свойства total_rows равно 4. Это имеет принципиальное значение. Представления возвращают не только результаты запросов, но и мета-данные (например, число выбранных документов), которые позволяют оценить результаты до разбора JSON. Результаты в формате JSON показаны в листинге 10.

Листинг 10. Документы JSON, отсортированные по дате
{"total_rows":4,"offset":0,"rows":[
  {"id":"85d4dbf45747e45406e5695b4b5796fe","key":"2009/01/30",
   "value":
    {"_id":"85d4dbf45747e45406e5695b4b5796fe","_rev":"1318766781",
     "officer":"Anthony Richards",
     "location":"54th and Main","vehicle_plate":"Virginia FCD-4444",
     "offense":"Parked in no parking zone","date":"2009/01/30"}},
  {"id":"1234334325","key":"2009/01/31",
   "value":
    {"_id":"1234334325","_rev":"4205717256",
     "officer":"Kristen Ree",
     "location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
     "offense":"Parked in no parking zone",
     "date":"2009/01/31"}},
  {"id":"12345","key":"2009/01/31",
   "value":
    {"_id":"12345","_rev":"1479261876",
     "officer":"Anthony Richards","location":"1893 Main St",
     "vehicle_plate":"Maryland 4433-OP",
     "offense":"Parked in no parking zone","date":"2009/01/31"}},
  {"id":"12339892938945","key":"2009/02/01",
   "value":
    {"_id":"12339892938945","_rev":"12351463","officer":"Anthony Richards",
     "location":"Walmart Parking lot","vehicle_plate":"Maine 4433-OP",
     "offense":"Parked in non-parking space",
    "date":"2009/02/01"}}]}

При работе с представлениями интересен тот факт, что вы можете передавать в них ключ, который затем будет выступать в качестве первого аргумента функции emit. Например, представление, показанное в листинге 8, просто сортирует документы по дате. Если же вы хотите получить только документы, имеющие некоторую определенную дату, то передайте ее в качестве ключа в запрос к представлению. Например, попробуйте обратиться в браузере по следующему URL:

http://localhost:5498/parking_tickets/_view/dates/by_date?key="2009/01/31"

В результате представление вернет только извещения, выданные 31 января. Вы должны увидеть в своем браузере фрагмент JSON, аналогичный показанному в листинге 11. Обратите внимание, что использование браузера позволяет легко просматривать ответы сервера в формате JSON.

Листинг 11. Только два извещения были выписаны 31 января
{"total_rows":4,"offset":1,"rows":[
   {"id":"1234334325","key":"2009/01/31",
    "value":
     {"_id":"1234334325","_rev":"4205717256","officer":"Kristen Ree",
       "location":"199 Baldwin Dr","vehicle_plate":"Maryland 77777",
       "offense":"Parked in no parking zone",
       "date":"2009/01/31"}},
   {"id":"12345","key":"2009/01/31",
    "value":
     {"_id":"12345","_rev":"1479261876","officer":"Anthony Richards",
       "location":"1893 Main St","vehicle_plate":"Maryland 4433-OP",
       "offense":"Parked in handicap zone without permit",
        "date":"2009/01/31"}}]}

Условия выборки документов в представлении могут быть настолько специализированными, насколько требуется. Например, при помощи простых манипуляций со строками в JavaScript можно создать представление для выборки извещений, выданных где-либо на Main Street (листинг 12).

Листинг 12. Еще одно представление, демонстрирующее возможности работы со строками
function(doc) {
  if(doc.location.toLowerCase().indexOf('main') > 0){
   emit(doc.location, doc);
  }
}

Как видно из листинга 12, документы будут передаваться в функцию emit, если значение свойства location содержит строку "main". Учтите, что подобное представление может вернуть большое число документов, например, все те, которые содержат строку "Germaine Street". В нашем случае представление должно вернуть результаты, показанные в листинге 13.

Листинг 13. Извещения с адресом, включающим Main Street
{"total_rows":2,"offset":0,"rows":[
  {"id":"123433432asdefasdf4325","key":"4th and Main",
   "value":
    {"_id":"123433432asdefasdf4325","_rev":"498239926",
    "officer":"Chris Smith","location":"4th and Main",
      "vehicle_plate":"VA FGA-JD33",
      "offense":"Parked in no parking zone","date":"2009/02/01"}},
 {"id":"123433432223e432325","key":"54 and Main",
   "value":
    {"_id":"123433432223e432325","_rev":"841089995",
    "officer":"Kristen Ree","location":"54 and Main Street",
      "vehicle_plate":"Maryland 77777",
      "offense":"Parked in no parking zone","date":"2009/02/02"}}]}

Обратите внимание на то, что фрагмент JSON содержит элемент key, который объясняет, почему данный документ был включен в выборку. Подобная информация часто оказывается весьма полезной. Кроме того, следует отметить несогласованность информации в извещениях, например, не все адреса заданы точно. Такие данные можно хранить в обычной реляционной БД, однако для них особенно подходит документ-ориентированная модель. Наконец, мощь Groovy и HTTPBuilder заключается в автоматическом разборе фрагментов JSON, что значительно облегчает доступ к данным (он оказывается намного проще, чем при работе с JDBC).

CouchDB - СУБД для Web

CouchDB представляет интерес во многом потому, что с ней удивительно легко начать работать. Реляционные СУБД также просты в использовании, однако у CouchDB есть дополнительное преимущество: вы можете с легкостью задействовать предоставляемые ею API при помощи, например, Web-браузера. Более того, эти API следуют принципам REST, а следовательно, вы можете с ними работать через такие удобные библиотеки, как HTTPBuilder и RESTClient. Кроме того, вы не обязаны использовать именно HTTPBuilder, поскольку существует множество Java-библиотек, также облегчающих работу с CouchDB. Одной из наиболее многообещающих библиотек является jcouchdb (см. раздел Ресурсы), которая полностью скрывает детали разбора JSON и обращения к ресурсам REST, позволяя обращаться к документам и представлениям в Java.

Оставайтесь с нами, и в следующей статье мы вернемся к платформе Google App Engine. Следуя духу времени, на сцену выходят все новые технологии, в частности, те, которые упрощают разработку и развертывание приложений для Google App Engine. Одна из них станет предметом рассмотрения в следующей статье.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Технология Java
ArticleID=643975
ArticleTitle=Вторая волна разработки Java-приложений: Работа с CouchDB через интерфейсы REST при помощи RESTClient в Groovy
publish-date=03302011