Вторая волна разработки Java-приложений: Работа с CouchDB через интерфейсы REST при помощи RESTClient в Groovy

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

Инновационный прорыв в области открытых технологий, который наблюдался в последние годы, повысил продуктивность разработчиков Java-приложений. Множество бесплатных библиотек, инфраструктур и законченных решений позволило существенно сократить время на создание продуктов. В этой нише свободных технологий особое место занимает Apache CouchDB, которую иногда называют СУБД для Web 2.0. Концепция этой СУБД интуитивно понятна, а работа с ней не сложнее использования Web-браузера. Эта статья серии Вторая волна разработки Java-приложений рассказывает о том, как эффективно использовать преимущества данной СУБД при помощи Groovy-библиотеки RESTClient.

Эндрю Гловер, президент компании, Stelligent Incorporated

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



30.03.2011

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

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

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

Об этой серии

Характерные черты разработки на Java существенно изменились с момента выхода первого релиза платформы. Благодаря зрелости открытых инфраструктур и аренде надежных сред развертывания, есть возможность собирать, тестировать и поддерживать Java-приложения без серьезных временных и денежных затрат. В этой серии Эндрю Гловер описывает ряд технологий, лежащих в основе новой парадигмы создания приложений на Java.

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

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

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

JSON

JSON – это легковесный формат для обмена данными, также представляющий собой альтернативу XML для Web-приложений. Он похож на XML, однако существенно лаконичнее. Благодаря своей легковесности он постепенно становится своего рода средством межъязыкового общения в Web. Более подробную информацию о JSON можно получить по ссылке, приведенной в разделе Ресурсы.

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

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

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

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

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

MapReduce

MapReduce, разработанная компанией Google, представляет собой принципиальную инфраструктуру для обработки гигантских объемов данных (см. раздел Ресурсы), оптимизированную для распределенных вычислений на большом числе вычислительных узлов. Она представляет собой комбинацию двух функций: map (отображение) и reduce (сведение). Функция отображения заключается в разделении большого объема данных на меньшие куски, которые затем могут быть переданы другим обрабатывающим процессам. Сведение представляет собой интеграцию отдельных результатов обработки данных в единый интегральный результат.

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

REST

Передача репрезентативного состояния (Representational state transfer – REST) – это принцип создания слабо связанных Web-приложений, основывающихся на ресурсах, имеющих имена, т.е. URL (Uniform Resource Locator), URI (Uniform Resource Identifier) или URN (Uniform Resource Name), а не на передаче сообщений. REST базируется на HTTP – отлично себя зарекомендовавшей инфраструктуре Web. Другими словами, сервисы REST используют такие аспекты протокола HTTP, как запросы типа GET и POST. Эти запросы прекрасно соответствуют стандартным нуждам бизнес-приложений, в частности операциям создания, чтения, изменения и удаления объектов (CRUD).

Как вы уже заметили, работа с 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

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

Рисунок 2. Интерфейс для выбора представлений в Futon
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

Далее вам потребуется ввести архитектурное имя документа (введите 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. Одна из них станет предметом рассмотрения в следующей статье.


Загрузка

ОписаниеИмяРазмер
Исходный код примеров к статьеj-javadev2-5.zip2 KБ

Ресурсы

Научиться

  • Оригинал статьи: Java development 2.0: REST up with CouchDB and Groovy's RESTClient (Эндрю Гловер, developerWorks, ноябрь 2009 г.). (EN)
  • Посетите официальный сайт проекта Apache CouchDB. (EN)
  • Ознакомьтесь с библиотеками HTTPBuilder и RESTClient, облегчающими работу с сервисами REST в Groovy. (EN)
  • Узнайте больше о Grape – системе управления пакетами в Groovy. (EN)
  • Прочитайте статью Изучение Аjax, часть 10: обмен данными в формате JSON (Бретт Маклафлин, Brett McLaughlin, developerWorks, март 2007) и получите опыт использования JSON. (EN)
  • Посетите статью в Википедии, посвященную MapReduce, в которой объясняется эта программная модель, служащая для обработки больших объемов данных. (EN)
  • Ознакомьтесь со статьей Вторая волна разработки Java-приложений: аренда сервера EC2 (Эндрю Гловер, developerWorks, сентябрь 2009 г.), в которой содержится практическое введение в разработку и развертывание приложений на платформе Amazon Elastic Compute Cloud (EC2). (EN)
  • В путеводителе Создание Web-сервиса REST (Эндрю Гловер, developerWorks, июль 2008 г.) содержится пошаговое руководство по базовым понятиям REST, а также созданию приложений с использованием Restlets. (EN)
  • Прочитайте статью Пересекая границы: параллельное программирование на Erlang (Брюс Тейт, Bruce Tate, developerWorks, апрель 2006 г.) и узнайте больше об Erlang - языке, который завоевывает все большую популярность в области параллельного программирования, распределенных приложений и систем мягкого реального времени. (EN)
  • Обратите внимание на проект jcouchdb. (EN)
  • Обратитесь к магазину технической литературы, в котором представлены книги на данную и другие темы. (EN)

Получить продукты и технологии

  • Загрузите инструментарий AWS, представляющий собой модуль EC2 для Eclipse. (EN)
  • Загрузите Groovy. (EN)
  • Загрузите последнюю версию CouchDB. (EN)

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


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

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


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