Большинство приложений имеют дело с типом данных «главный / подробный»:
- пивоварни и пиво
- отдел и сотрудники
- счета и предметы
- …
Это необходимо, например, для создания представления приложения следующим образом:
С Couchbase и многими документно-ориентированными базами данных у вас есть разные способы справиться с этим, вы можете:
- Создайте отдельный документ для каждого мастера и вставьте в него всех детей
- Создайте основной и дочерний документы и свяжите их, используя атрибут.
В первом случае, когда вся информация хранится в одном документе, довольно просто использовать весь набор данных и, например, создать экран, который показывает всю информацию, но как насчет второго случая? В этом посте я объясняю, как можно использовать представления Couchbase, чтобы упростить создание основных / подробных видов. Как бывший сотрудник Oracle, я использую печально известную схему SCOTT с таблицами DEPT и EMP, как первый пример. Затем в конце я добавлю это к образцу пива, предоставленному Couchbase.
Данные
Couchbase — это база данных без схемы, и вы можете хранить в ней «все, что захотите», но для этого вам нужно использовать документы JSON и создавать документы двух типов: «отдел» и «сотрудник». Обычно мы используем технический атрибут для ввода документа. Таким образом, документ сотрудника и отдела будет выглядеть следующим образом:
отдел
|
1
2
3
4
5
6
|
{ 'type': 'dept', 'id': 10, 'name': 'Accounting', 'city': 'New York'} |
Сотрудник
|
1
2
3
4
5
6
7
8
9
|
{ 'type': 'emp', 'id': 7782, 'name': 'Blake', 'job': 'Clark', 'manager': 7839, 'salary': 2450, 'dept_id': 'dept__10'} |
Это показывает только документ, в Couchbase вы должны связать документ с ключом. Для этого примера я использую простой шаблон:
type__id, для этих документов ключи будут выглядеть следующим образом:
- dept__10
- emp__20
Вы можете использовать любой шаблон для создания ключа, например, для сотрудника, которого вы выбрали для размещения электронного письма. Обратите внимание на атрибут «dept_id» в документе сотрудника. Это ключ отдела; Вы можете видеть это как «внешний ключ». Но помните, что отношения между документами отдела и сотрудника полностью управляются приложением, Couchbase Server не применяет их. Я создал Zip-файл, который содержит все данные, вы можете скачать его здесь ; и импортируйте данные в Couchbase с помощью утилиты cbdocloader. Для импорта данных выполните следующую команду из окна терминала:
|
1
|
./cbdocloader -n 127.0.0.1:8091 -u Administrator -p password -b default ~/Downloads/emp-dept.zip |
Вы можете узнать больше об инструменте cbdocloader в документации .
Вид
Запросы внутри Couchbase основаны на представлениях ; и представления строят индексы, поэтому мы должны создать представление, а точнее «сопоставленное представление». Идея создания объединенного представления состоит в том, чтобы создать индекс, в котором ключи упорядочены так, что сначала появляется родительский идентификатор, а затем его дочерние элементы. Итак, мы генерируем индекс, который будет выглядеть так:
DEPT_10, Бухгалтерский учет
DEPT_10, Блейк
DEPT_10, Миллер
DEPT_20, Исследования
DEPT_20, Адамс
DEPT_20, Ford
…
Это на самом деле довольно легко сделать с представлениями Couchbase. Единственная хитрость здесь — это контролировать порядок и быть уверенным, что хозяин всегда первый, прямо перед своими детьми. Таким образом, чтобы контролировать это, мы можем создать составной ключ, который содержит идентификатор отдела, элемент «сортировки» и имя (пиво или пивоварня). Таким образом, функция карты вида выглядит следующим образом:
|
01
02
03
04
05
06
07
08
09
10
11
12
|
function (doc, meta) { if (doc.type == "emp" || doc.type == "dept") { switch(doc.type) { case "dept" : emit( [meta.id, 0, doc.name], 0 ); break; case "emp" : emit( [doc.dept_id, 1, doc.name ], doc.salary + ((doc.comm)?doc.comm:0) ); break; } }} |
Ключ состоит из:
- идентификатор отдела, извлеченный из самого документа отдела или из документа сотрудника в зависимости от типа документа
- произвольное число, которое используется для управления порядком. Я поставил 0 для отдела, 1 для работника
- название отдела или сотрудника, это также позволяет отсортировать результат по имени
В дополнение к ключу, это представление используется для получения некоторой информации о зарплате сотрудников. Заработная плата — это просто сумма зарплаты плюс комиссия, когда она существует. Результат просмотра выглядит так:
В этом представлении вы можете теперь использовать результат представления для создания отчета для вашего приложения. Можно также использовать параметры в вашем запросе, чтобы просмотреть только часть данных, например, по отделам, используя, например, startkey = [‘dept__20’, 0] & endkey = [‘dept__20’, 2], чтобы просмотреть только данные -Департамент и сотрудники- отдела 20-исследования.
Пример пива
Вы можете создать эквивалентное представление для приложения-образца пива, в котором вы печатаете все пивоваренные заводы и пиво в одном отчете. Представление называется all_with_beers в проектной документации «пивоварня». Вид выглядит так:
|
01
02
03
04
05
06
07
08
09
10
11
|
function(doc, meta) { switch(doc.type) { case "brewery": emit([meta.id, 0, doc.name]); break; case "beer": if (doc.name && doc.brewery_id) { emit([doc.brewery_id, 1, doc.name], null); } } } |
После того, как вы опубликуете его в производстве, вы можете использовать его в приложении Beer Sample, для этого примера я изменил пример приложения Java.
Создайте сервлет для обработки запроса пользователя и / URI.
BreweryAndBeerServlet, который вызывает представление, используя следующий код:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
View view = client.getView("brewery", "all_with_beers");Query query = new Query();query.setIncludeDocs(true).setLimit(100);ViewResponse result = client.query(view, query);ArrayList<HashMap<String, String>> items = new ArrayList<HashMap<String, String>>();for(ViewRow row : result) { HashMap<String, String> parsedDoc = gson.fromJson( (String)row.getDocument(), HashMap.class); HashMap<String, String> item = new HashMap<String, String>(); item.put("id", row.getId()); item.put("name", parsedDoc.get("name")); item.put("type", parsedDoc.get("type")); items.add(item);}request.setAttribute("items", items);request.getRequestDispatcher("/WEB-INF/breweries/all.jsp") .forward(request, response); |
Результат запроса устанавливается в HttpRequest и выполняется страница all.jsp. JSP использует JSTL для печати информации, используя следующий код:
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
<table id="brewery-table" class="table table-striped"> <thead> <tr> <th>Name</th> <th></th> <th></th> </tr> </thead> <tbody> <c:forEach items="${items}" var="item"> <c:if test="${ item.type == 'brewery' }"> <tr> <td colspan="2"><strong><a href="/breweries/show/${item.id}">${item.name}</a></strong></td> <td><a class="btn btn-small btn-danger" href="/breweries/delete/${item.id}">Delete</a> </td> </tr> </c:if> <c:if test="${ item.type == 'beer' }"> <tr> <td></td> <td><a href="/beers/show/${item.id}">${item.name}</a></td> <td> <a class="btn btn-small btn-danger" href="/beers/delete/${item.id}">Delete</a> <a class="btn btn-small btn-warning" href="/beers/edit/${item.id}">Edit</a> </td> </tr> </c:if> </c:forEach> </tbody></table> |
JSP получает элементы из HTTP-запроса и циклически обрабатывает каждый элемент, а затем на основе типа элемента, на который выводится информация. Конечный результат выглядит так:
Это расширение к приложению Beer Sample доступно здесь: https://github.com/tgrall/beersample-java/tree/BreweriesAndBeers
Ссылка: Введение в сопоставленные представления с Couchbase 2.0 от нашего партнера по JCG Тугдуала Граля в блоге Tug’s Blog .

