Статьи

Базы данных NOSQL для Web CRUD (CouchDB) — Шоу / Представления

Есть много приложений, которые легко поддаются парадигме CRUD. Даже если только 80% функциональности приложения — это чистый CRUD, можно воспользоваться более простой моделью хранения. В течение многих лет многие (в том числе и я) думали, что хранение состояния приложения, которое необходимо использовать в приложениях корпоративного уровня, означало, что у нас был один вариант — СУБД. Не то чтобы другие модели были недоступны, но их распространенность была не такой высокой, что ставило под сомнение качество / стабильность и долгосрочное состояние такого программного обеспечения. Таким образом, мы привыкли приближаться к постоянству государства, вставляя все в одну дыру. Если он не подходил, мы обрезали его, разрезали, сжали, поставили в тупик, но мы подогнали его. Затем, когда пришло время вытащить, ах, мы повторили процедуру. ОРМ являются одним из самых популярных средств для таких процедур.Но если кто-то когда-либо разрабатывал сложную модель данных и действительно занимал время, чтобы подумать о стратегии доступа к данным как на стороне приложения, так и в СУБД, вы быстро столкнулись бы со многими ограничениями модели ORM. Я думаю, вы можете абстрагироваться отСопротивление импеданса только так сильно, но следите за этими неплотными абстракциями . Так что, если вы все еще не уверены в своем SQL и реляционной теории, потому что великие боги обещали, что вам никогда не придется беспокоиться об этом, если вы используете ORM, вам лучше приступить к обучению, если вы не планируете поддерживать приложение ToDo List до конца твоей жизни.

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

  1. Высокодинамичная структура (реляционные схемы довольно статичны, если вы делаете это реляционным способом (без высоких / тощих таблиц))
  2. Модель данных не очень реляционная. Это говорит само за себя, но многие на самом деле не знают, когда и как это определить, поскольку мы потратили так много времени на выявление отношений, которые не существуют или не имеют отношения к приложению.
  3. Ваша реляционная схема денормализована до такой степени, что вы больше не пользуетесь такими функциями реляционной базы данных, как обеспечение согласованности и уменьшение избыточности данных.
  4. Ваша реляционная база данных изгибается в обратном направлении, чтобы обеспечить пропускную способность чтения / записи даже после того, как вы денормализовали (что само по себе является поводом для поиска в другом месте) и оптимизированы, вынуждая вас постоянно увеличивать масштаб, чтобы обеспечить повышенную нагрузку.
  5. Вы постоянно выполняете маршаллизацию / демаршаллирование данных (ORM ???), чтобы сохранить их, а затем преобразовать в другой формат данных.

Касаясь немного больше о пуле № 5; Много программного обеспечения написано с использованием хороших ОО-принципов инкапсуляции. Инкапсуляция — это сердце программных абстракций и, возможно, самый важный принцип. Но люди склонны злоупотреблять этим. Абстракции хороши, когда они увеличивают ценность, но маршалинг и демаршалирование одной структуры данных в другую без веской видимой причины, кроме того, что вам не нужно учиться работать с конкретной структурой данных, я не уверен, что это хороший причина. Так много программных проектов используют ORM ради того, чтобы не изучать SQL, но как далеко вы на самом деле можете получить? ORM является прекрасным примером утечки абстракции, Так много проектов извлекают данные из веб-представления в формате JSON или в кодировке URL и переносят их в объекты только для проверки данных и их сохранения с помощью ORM. Итак, теперь вы распаковали данные из JSON в граф объектов, чтобы просто затем снова перенаправить их в запрос SQL для отправки в базу данных. Нужны ли нам эти лишние шаги?

Я уверен, что есть и другие причины, о которых я не упомянул здесь. С этими причинами я лично столкнулся при принятии своих решений.

Рациональный способ принятия решения о сохранении данных состоит не в том, чтобы автоматически начать писать сценарий DDL или захватить инструмент ER-диаграммы, а в том, чтобы посмотреть, какие данные у вас есть, как эти данные сохранятся «естественным» образом, как работает клиентское программное обеспечение. необходимо получить доступ к этим данным, каковы соображения производительности / масштабируемости, а затем пойти и посмотреть на различные модели постоянства, чтобы найти лучшее соответствие.

В моем последнем проекте мне пришлось подумать о способе сохранения иерархических данных. Эти данные будут доступны через какой-либо веб-носитель (браузер, мобильный клиент и т. Д.) Большую часть времени. Один из веб-интерфейсов будет веб-приложением с поддержкой ajax, другой — приложением для iphone и / или adroid. JSON — это протокол общения в Интернете. Кто-то будет утверждать, что это XML, но я пока оставлю свои мнения о себе.

CouchDB — это база данных документов, которую можно назвать хранилищем ключей / значений. Это позволяет хранить документы JSON, которые однозначно идентифицируются ключами. Звучит интересно, не совсем. Существуют десятки других баз данных с такими же возможностями, так почему же CouchDB? Хорошо в одном коротком предложении: CouchDB — это сборка для Интернета и Интернета. Так, что это действительно означает? Ну, кроме структуры хранения JSON и ее врожденной способности к горизонтальному масштабированию, они создали несколько довольно удивительных функций, которые делают его очень привлекательным для конкретного типа приложения. Задача состоит в том, чтобы решить, является ли приложение, которое вы создаете, тем приложением. Поэтому, чтобы не создавать этот пост дольше, чем он уже есть в моей статье, позвольте мне описать и продемонстрировать некоторые функции, которые я использовал за последние несколько дней, и почему они актуальны.

Пожалуйста, убедитесь, что у вас установлена ​​версия couchdb 0.10. *, А также утилита командной строки curl. Для инструкций по установке смотрите http://wiki.apache.org/couchdb/Installation

После установки couchdb вы можете запустить его с помощью команды couchdb. В зависимости от ваших настроек, вы можете сделать…

sudo couchdb

Немного фона, хотя, прежде чем мы продолжим …

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

CouchDB предоставляет RESTful API, поэтому его довольно легко использовать с любого языка, который поддерживает HTTP. В большинстве популярных языков есть библиотеки абстракций, чтобы абстрагировать HTTP-абстракцию. Вот список доступных клиентов: http://wiki.apache.org/couchdb/Basics. Для наших целей мы будем использовать curl , утилиту командной строки, которая позволяет нам делать HTTP-запросы. Итак, давайте посмотрим, как мы можем легко сделать это с CouchDB.

Теперь, когда CouchDB успешно работает, давайте создадим базу данных и вставим пример данных…

curl -X PUT «http: // localhost: 5984 / sample_db»

Над строкой создайте базу данных с именем sample db. Если команда выполнена успешно, вы увидите следующий вывод: _ {“ok”: true} . Теперь давайте добавим три файла в эту базу данных. Файлы данных JSON, которые мы отправляем ниже, находятся в приведенных ниже фрагментах кода с соответствующей маркировкой, поэтому убедитесь, что они находятся в каталоге, из которого вы выполняете команды ниже.

curl -X PUT -d @ rec1.json «http: // localhost: 5984 / sample_db / record1» curl -X PUT -d @ rec2.json «http: // localhost: 5984 / sample_db / record2» curl -X PUT -d @ rec3.json «http: // localhost: 5984 / sample_db / record3»

Опять же, каждая команда должна выдавать ответ JSON с «ok», установленным в true, если добавление завершилось успешно. Вот что можно ожидать от первой команды: {«ok»: true, «id»: «record1», «rev»: «1-7c15e9df17499c994439b5e3ab1951d2»} . Опять же, ok установлено на true, что делает этот ответ успешным. В поле id указано имя записи, которую мы создали. Вы можете видеть, что имена задаются через URL, поскольку они являются просто ресурсами в мире REST. оборотовполе отображает ревизию этого документа. Модель параллелизма CouchDB основана на MVCC, хотя она обновляет документы по мере их обновления, поэтому каждая модификация документа получает свой уникальный идентификатор ревизии. Вы можете узнать больше об этом в документации по архитектуре и API CouchDB.

rec1.json

 {
"name": "John Doe",
"date": "2001-01-03T15:14:00-06:00",
"children": [
{"name": "Brian Doe", "age": 8, "gender": "Male"},
{"name": "Katie Doe", "age": 15, "gender": "Female"}
]
}

 

rec2.json

{
"name": "Ilya Sterin",
"date": "2001-01-03T15:14:00-06:00",
"children": [
{"name": "Elijah Sterin", "age": 10, "gender": "Male"}
]
}

 

rec3.json

{
"name": "Emily Smith",
"date": "2001-01-03T15:14:00-06:00",
"children": [
{"name": "Mason Smith", "age": 3, "gender": "Male"},
{"name": "Donald Smith", "age": 2, "gender": "Male"}
]
}

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

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

 function(doc) {
if (doc.name == "Ilya Sterin") {
emit(null, doc);
}
}

Есть еще две действительно интересные функции, которые позволяют более эффективно фильтровать и преобразовывать данные. Эти функции являются шоу и списки . Целью шоу и списков является визуализация документа JSON в другом формате. Шоу позволяют преобразовать один документ в другой формат. Шоу аналогичны функция зрения, но она принимает два параметра функцию (DOC, REQ) , документ представляет собой экземпляр документа итерируемого и запрос является абстракцией над CouchDB объектом запроса. Вот простая функция шоу

function(doc, req) {
var person = ;
person.@name = doc.name;
person.@joined = doc.date;
person.children = ;
if (doc.children) {
for each (var chldInst in doc.children) {
var child = ;
child.text()[0] = chldInst.name;
child.@age = chldInst.age;
child.@gender = chldInst.gender;
person.children.appendChild(child);
}
}
return {
'body': person.toXMLString(),
'headers': {
'Content-Type': 'application/xml'
}
}
}

 

Функция xml и inline, которые вы видите здесь, это e4x, который добавляет встроенную поддержку как часть ECMAScript и реализован во встроенном движке javascript Spidermonkey , который использует CouchDB.

Эта функция показа берет конкретную запись JSON и превращает ее в XML. Создать шоу довольно просто, вы просто инкапсулируете вышеописанную функцию в проектный документ и создаете запись через PUT.

Вот проектная документация для шоу выше …

xml_show.json


{
"shows": {
"toxml": "Here you inline the show function above. Make sure all double quotes are escaped..."
}
}

Получив проектный документ, создайте его …

curl -X PUT -H «Тип содержимого: application / json» -d @ xml_show.json «http: // localhost: 5984 / sample_db / _design / shows»

Примечание: в (… ./_ дизайн / шоу) шоу — это просто название проектного документа, его можно называть как угодно

Теперь давайте вызовем шоу

curl -X GET «http: // localhost: 5984 / sample_db / _design / shows / _show / toxml / record1»

Вот вывод

<person name="John Doe" joined="2001-01-03T15:14:00-06:00">
<children>
<child age="8" gender="Male">Brian Doe</child>
<child age="15" gender="undefined">Katie Doe</child>
</children>
</person>

 

Итак, это было очень просто, мы сохранили наш документ, который не требовал кода от нашего имени, и затем мы извлекли его с минимальными усилиями, используя возможности e4x ECMAScript.

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

function(head, req) {
start({'headers': {'Content-Type': 'application/xml'}});
var people = ;
var row;
while (row = getRow()) {
var doc = row.value;
var person = ;
person.@name = doc.name;
person.@joined = doc.date;
person.children = ;
if (doc.children) {
for each (var chldInst in doc.children) {
var child = ;
child.text()[0] = chldInst.name;
child.@age = chldInst.age;
child.@gender = chldInst.gender;
person.children.appendChild(child);
}
}
people.appendChild(person);
}
send(people.toXMLString());
}

 

Опять же, вы инкапсулируете эту функцию списка в проектный документ вместе с простой функцией просмотра

xml_list.json

  {
"views": {
"all": {
"map": "function(doc) { emit(null, doc); }"
}
},
"lists": {
"toxml": "Here you inline the show function above. Make sure all double quotes are escaped as it must be stringified due to the fact that JSON can't store a function type."
}
}

 

Теперь мы создаем дизайн документа

curl -X PUT -H «Тип контента: application / json» -d @ xml_list.json «http: // localhost: 5984 / sample_db / _design / lists»

Как только проектный документ создан, мы можем запросить наш XML-документ со списком всех записей персонала.

curl -X GET http: // localhost: 5984 / sample db / design / lists / _list / toxml / all

И вывод

<people>
<person name="John Doe" joined="2001-01-03T15:14:00-06:00">
<children>
<child age="8" gender="Male">Brian Doe</child>
<child age="15" gender="Female">Katie Doe</child>
</children>
</person>
<person name="Ilya Sterin" joined="2001-01-03T15:14:00-06:00">
<children>
<child age="10" gender="Male">Elijah Sterin</child>
</children>
</person>
<person name="Emily Smith" joined="2001-01-03T15:14:00-06:00">
<children>
<child age="3" gender="Male">Mason Smith</child>
<child age="2" gender="Male">Donald Smith</child>
</children>
</person>
</people>

Таким образом, вы можете увидеть, как шоу и списки очень полезны и предоставляют удобный способ для преобразования видов в различные форматы.

Как видите, мы создали базу данных и сохранили данные. Для этого не требуется никакого кода, просто соберите данные через ваше приложение и сделайте запрос CouchDB REST. Мы также добавили некоторые пользовательские функции преобразования данных для потребления несколькими клиентами с помощью шоу и представлений . На мой взгляд, CouchDB — это отличный шаг к тому, что можно назвать веб / облачной базой данных. Он обладает потрясающими возможностями интеграции с веб-технологиями и может масштабироваться для поддержки постоянно растущего масштаба данных в сети. Другими словами, он подходит для некоторых моделей приложений, как перчатки.

Я едва даже поцарапал верхушку айсберга того, что может сделать CouchDB. Мы не говорили об агрегатах результатов, которые могут быть достигнуты с помощью map / Reduce, мы также не обсуждали проверку данных и безопасность. Эти функции могут быть главой некоторых будущих сообщений.

Вы можете найти больше связанных постов / информации в блоге Ильи .