在CouchDB中使用map reduce来输出更少的行

时间:2011-05-19 21:17:12

标签: database join map couchdb reduce

假设您有两种文档类型,客户订单客户文档包含基本信息,如姓名,地址等。订单包含每次客户订购时的所有订单信息。存储文档时,type = order或type = customer。

如果我在一组10个客户和30个订单上执行地图功能,它将输出40行。有些行是客户,有些是订单。

问题是,如何编写reduce,以便订单信息“填充”在具有客户信息的行内?因此它将返回10行(10个客户),但每个客户的所有相关订单。

基本上我不想在输出上单独记录,我想将它们组合在一起(订单分成一个客户行)我觉得减少就是这样吗?

1 个答案:

答案 0 :(得分:30)

这称为 view collat​​ion ,它是一种非常有用的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。如果您遵循以下所有内容:而不是12,则客户的值可能更高null,然后是订单的订单时间戳。它们将像以前一样进行排序,除非您现在有一个按时间顺序排列的订单列表。