假设您有两种文档类型,客户和订单。 客户文档包含基本信息,如姓名,地址等。订单包含每次客户订购时的所有订单信息。存储文档时,type = order或type = customer。
如果我在一组10个客户和30个订单上执行地图功能,它将输出40行。有些行是客户,有些是订单。
问题是,如何编写reduce,以便订单信息“填充”在具有客户信息的行内?因此它将返回10行(10个客户),但每个客户的所有相关订单。
基本上我不想在输出上单独记录,我想将它们组合在一起(订单分成一个客户行)我觉得减少就是这样吗?
答案 0 :(得分:30)
这称为 view collation ,它是一种非常有用的CouchDB技术。
幸运的是,您甚至不需要reduce
步骤。只需使用map
即可让客户及其订单“聚集在一起”。
关键是您需要为每个客户提供唯一的ID,并且必须从客户文档和订单文档中了解它。
客户示例:
{ "_id": "customer me@example.com"
, "type": "customer"
, "name": "Jason"
}
示例顺序:
{ "_id": "abcdef123456"
, "type": "order"
, "for_customer": "customer me@example.com"
}
我已经方便地将客户ID用作文档_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);
}
}
所有行将主要对文档所关注的客户进行排序,“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
P.S。如果您遵循以下所有内容:而不是1
和2
,则客户的值可能更高null
,然后是订单的订单时间戳。它们将像以前一样进行排序,除非您现在有一个按时间顺序排列的订单列表。