Большинство приложений имеют дело с типом данных «главный / подробный»:
- пивоварни и пиво
- отдел и сотрудники
- счета и предметы
- …
Это необходимо, например, для создания представления приложения следующим образом:
С 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 .