ForeverLearning
ForeverLearning

Reputation: 6705

MongoDB Map/Reduce struggles

Given a document like this:

{    "_id": { 
    "$oid": "4d88ca367d190a0aa4e27806"    },    "Rows": [ 
    { 
      "Columns": { 
        "Date": "Tue, 02 Aug 2011 00:00:00 GMT -04:00", 
        "Col2": 33 
        "Col3": 44 
      } 
    }, 
    { 
      "Columns": { 
        "Date": "Mon, 17 Oct 2011 00:00:00 GMT -04:00", 
        "Col2": 55 
        "Col3": 66 
      } 
    }    ],    "DocName": "For My Eyes Only",    "DocIdentifier": 3322445  }

and the following Map/Reduce functions:

function() { 
  this.Rows.forEach(function(bulkcol) { 
    emit(this.DocName, { TrendValue: bulkcol.Columns.Col2 }); 
    }); 
}; 

function(key, values) { 
  var sum = 0; 
  values.forEach(function(currTrend) { 
    sum += currTrend.TrendValue; 
  }); 
  return {DocName: key, TrendValue: sum}; 
}; 

I get the following output:

{ 
  "_id": null, 
  "value": { 
    "DocName": null, 
    "TrendValue": 88 
  } 
} 

Why is the DocName null?

Upvotes: 1

Views: 859

Answers (2)

AdaTheDev
AdaTheDev

Reputation: 147354

The problem is very much as Srdjan indicated - inside your forEach function, you don't actually have a reference to the parent document.

If you change your map function to this, it works:

m = function() {
   var docName = this.DocName;
   this.Rows.forEach(function(bulkcol) {
     emit(docName, { TrendValue: bulkcol.Columns.Col2 });
     });
 };

So, assign the doc name into a variable before the loop, and then use that within it

Upvotes: 1

Srdjan Pejic
Srdjan Pejic

Reputation: 8212

If I'm looking at this right, and I'd like to think that I am, the this in the emit function is not what you're expecting it to be.

Since it's inside a function, that this refers to each Row, not the parent document. Try this:

function() {
  this = parent;
  this.Rows.forEach(function(bulkcol) { 
  emit(parent.DocName, { TrendValue: bulkcol.Columns.Col2 }); 
  }); 
}; 

Upvotes: 0

Related Questions