Статьи

Введение в сопоставленные виды с Couchbase 2.0

Большинство приложений имеют дело с типом данных «главный / подробный»:

  • пивоварни и пиво
  • отдел и сотрудники
  • счета и предметы

Это необходимо, например, для создания представления приложения следующим образом:

С 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 .