Использование карты уменьшить в CouchDB для вывода меньше строк - PullRequest
14 голосов
/ 20 мая 2011

Допустим, у вас есть два типа документов: клиенты и заказы . Документ customer содержит основную информацию, такую ​​как имя, адрес и т. Д., А orders содержит всю информацию о заказе каждый раз, когда клиент что-то заказывает. При хранении документов тип = заказ или тип = клиент.

Если я выполню функцию карты для набора из 10 клиентов и 30 заказов, то получится 40 строк. Некоторые строки будут клиентами, некоторые будут заказами.

Вопрос в том, как мне написать сокращение, чтобы информация о заказе была «заполнена» внутри строк, содержащих информацию о клиенте? Таким образом, он вернет 10 строк (10 клиентов), но все соответствующие заказы для каждого клиента.

По сути, я не хочу, чтобы на выходе были отдельные записи, я хочу объединить их (заказы в одну строку клиента) и думаю, что сокращение - это путь?

1 Ответ

30 голосов
/ 20 мая 2011

Это называется view collation , и это очень полезный метод CouchDB.

К счастью, вам даже не нужен шаг reduce.Просто используйте map, чтобы объединить клиентов и их заказы.

Настройка

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

Пример клиента:

{ "_id": "customer me@example.com"
, "type": "customer"
, "name": "Jason"
}

Пример заказа:

{ "_id": "abcdef123456"
, "type": "order"
, "for_customer": "customer me@example.com"
}

Я удобно использовал идентификатор клиента в качестве документа _id но важно то, что оба документа знают личность клиента .

Выплата

Цель - запрос карты, где, если вы укажете ?key="customer me@example.com", вы будетесначала вернуть (1) информацию о клиенте и (2) любой и все размещенные заказы.

Эта функция карты будет делать следующее:

function(doc) {
  var CUSTOMER_VAL = 1;
  var ORDER_VAL    = 2;
  var key;

  if(doc.type === "customer") {
    key = [doc._id, CUSTOMER_VAL];
    emit(key, doc);
  }

  if(doc.type === "order") {
    key = [doc.for_customer, ORDER_VAL];
    emit(key, doc);
  }
}

Все строки будут отсортированы в основном наcustomer, о котором идет речь, и сортировка "tiebreaker" - это целое число 1 или 2. Это позволяет клиентам всегда сортировать документы выше их соответствующих документов заказа.

["customer me@example.com", 1], ...customer doc...
["customer me@example.com", 2], ...customer's order...
["customer me@example.com", 2], ...customer's other order.
... etc...
["customer another@customer.com", 1], ... different customer...
["customer another@customer.com", 2], ... different customer's order

PS Если вы все это выполняете: вместо1 и 2 лучшее значение может быть nullдля клиента, затем отметка времени заказа для заказа.Они будут сортироваться так же, как и раньше, за исключением того, что теперь у вас есть хронологический список заказов.

...