This is called view collation and it is a very useful CouchDB technique.
Fortunately, you don't even need a reduce
step. Just use map
to get the customers and their orders "clumped" together.
Setup
The key is that you need a unique id for each customer, and it has to be known both from customer docs and from order docs.
Example customer:
{ "_id": "customer me@example.com"
, "type": "customer"
, "name": "Jason"
}
Example order:
{ "_id": "abcdef123456"
, "type": "order"
, "for_customer": "customer me@example.com"
}
I have conveniently used the customer ID as the document _id
but the important thing is that both docs know the customer's identity.
Payoff
The goal is a map query, where if you specify ?key="customer me@example.com"
then you will get back (1) first, the customer info, and (2) any and all orders placed.
This map function would do that:
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);
}
}
All rows will sort primarily on the customer the document is about, and the "tiebreaker" sort is either the integer 1 or 2. That makes customer docs always sort above their corresponding order docs.
["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
P.S. If you follow all that: instead of 1
and 2
a better value might be null
for the customer, then the order timestamp for the order. They will sort identically as before except now you have a chronological list of orders.