couchdb-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Daniel Sheppard" <>
Subject Is the current Map/Reduce plan too restrictive?
Date Fri, 18 Apr 2008 05:01:13 GMT
Suppose, I have three document types:

{ _id: "1234", type: "category" }
{ _id: "5678", type: "group", :category_id: "1234" }
{ _id: "9012", type: "item", :group_id: "5678" }

Now, to get all the items in a group, I'd have a view like so:

function(doc) {
  if(doc.type == "item") {
    map([doc.group_id, doc]);

and to get all the groups in a category:

function(doc) {
  if(doc.type == "group") {
    map([doc.category_id, doc]);

However, if I wanted to get all the items in a category, I'd need to
interrogate the db for the list of groups and then grab the list of
items for each group. Is that the only way? I tried thinking of various
ways to map/reduce the data, or double-map the data, but consistently
came up blank.

I know that this could be solved easily by denormalising the data so
that the items stored their category id, but I thought I'd be stubborn
to figure out other ways to do it. 

It would be possible if the reducer was no longer required to be a
combiner and could actually emit multiple documents from its data
however it wanted.

First map:

function(doc) {
  if(doc.type == "item") {
    map([doc.group_id, doc])
  } else if (doc.type =="group") {
    map([doc._id, doc])

Then a reduction of each key into new documents:

function(key, values) {
  var group;
  for(i=0; i < values.length; i++) {
    if(values[i].type == "group") {
      group = values[i];
  if(group) {
    for(i=0; i < values.length; i++) {
      if(values[i].type == "item") {
        map(group.category_id, item);

(and more advanced queries could go through further map/reduce cycles).

Damien's blog discussions on the map/reduce implementation seem to imply
that the reduce function should be reducing the values for a key down
into a single key,value pair, but Map/Reduce does not require that - as
shown in the example above, it's useful to be able to emit multiple
key/value pairs from the 'reduce', actually expanding the key/value set.
It is COMMON for the reduce function to emit a single value - it is not
necessary for Map/Reduce to be restricted in that way.


View raw message