Using map reduce in CouchDB to output fewer rows

守給你的承諾、 提交于 2019-11-28 18:25:17

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!