Re: [mongodb-user] mapReduce with day_of_week, month_of_year

97 views
Skip to first unread message

Scott Hernandez

unread,
Jun 21, 2012, 1:06:48 PM6/21/12
to mongod...@googlegroups.com
You are close.

Here is a reference for the javascript Date object:
http://www.w3schools.com/jsref/jsref_obj_date.asp

Here is an example in the shell:
> var now = new Date()
> now.getDay()
4
> now.getMonth()
5

Remember these are 0 based.


Also, don't forget to copy the date to your retVal object as you are
creating a new Date here:
var retVal = { count:0, date:new Date(), su:0, m:0, t:0, w:0, r:0, f:0, sa:0 };

On Thu, Jun 21, 2012 at 4:57 PM, Brad Karels <bka...@gmail.com> wrote:
> I am new to mongo and not a JavaScript ninja so forgive my silliness.  That
> said, I am looking to perform a mapreduce on a set of events to get counts
> by day of the week (i.e. What day of the week is most popular for events?)
>  My efforts have left me short around how to extract the day of week (or
> month of year) from a date inside the mapReduce function.  My solution thus
> far looks as follows:
>>>
>>> /* mongo localhost:27017/tracking countByDayOfWeek.js --shell */
>>>
>>>
>>> mapFunction=function() {
>>>
>>>      emit( this.source, { count:1, date:this.dateCreated, su:1, m:1, t:1,
>>> w:1, r:1, f:1, sa:1 } );
>>>
>>>  }
>>>
>>>
>>>
>>>  reduceFunction=function(k,vals) {
>>>
>>>     var retVal = { count:0, date:new Date(), su:0, m:0, t:0, w:0, r:0,
>>> f:0, sa:0 };
>>>
>>>
>>>
>>>      vals.forEach(function(value) {
>>>
>>>          retVal.count += value.count;
>>>
>>>          var day = value.date.getDay; // Here seems to be the sticky bit
>>>
>>>          if (day == 0) {
>>>
>>>              retVal.su += value.su;
>>>
>>>          }...{
>>>
>>>          } else {
>>>
>>>              retVal.sa += value.sa;
>>>
>>>          }
>>>
>>>      });
>>>
>>>      return retVal;
>>>
>>>  }
>>>
>>>
>>>
>>>  db.runCommand({
>>>
>>>      mapReduce: "track_event",
>>>
>>>      map: mapFunction,
>>>
>>>      reduce: reduceFunction,
>>>
>>>      out: "myOutput"
>>>
>>>  });
>
>
> I have been poking around here and other places a bit and have found date
> operations like this seem to yet be a bit limiting.  So if someone can put
> me down a more correct path I'd appreciate any advice moving forward.
>
> Thank you.
>
> --
> You received this message because you are subscribed to the Google
> Groups "mongodb-user" group.
> To post to this group, send email to mongod...@googlegroups.com
> To unsubscribe from this group, send email to
> mongodb-user...@googlegroups.com
> See also the IRC channel -- freenode.net#mongodb

William Z

unread,
Jun 21, 2012, 3:00:51 PM6/21/12
to mongod...@googlegroups.com

Hi Brad!

There seem to be a couple of problems with your map/reduce process, beyond just your problems with the getDay() function. 

1) For good help in debugging map/reduce (specifically, in debugging the output of the map() function), check out this page: http://www.mongodb.org/display/DOCS/Troubleshooting+MapReduce

2) I think that you should be checking for the specific day of the week in your map() function, and not in the reduce() function.  Remember, the reduce() function is only used to accumulate what's been emitted by the map() function.

Here is the code that I used to get the correct results for your problem:

map = function() {
    var day = this.date.getDay();
    var ret = { count: 1, su:0, mo:0, tu:0, we:0, th:0, fr:0, sa:0, };
    if ( day == 0 ) ret.su++;
    if ( day == 1 ) ret.mo++;
    if ( day == 2 ) ret.tu++;
    if ( day == 3 ) ret.we++;
    if ( day == 4 ) ret.th++;
    if ( day == 5 ) ret.fr++;
    if ( day == 6 ) ret.sa++;
    emit({ event: this.event }, ret );
}

reduce = function(key, values) {
  var ret = { count:0, su:0, mo:0, tu:0, we:0, th:0, fr:0, sa:0, }

  values.forEach(function(v) {
    ret.count += v.count;
    ret.su += v.su;
    ret.mo += v.mo;
    ret.tu += v.tu;
    ret.we += v.we;
    ret.th += v.th;
    ret.fr += v.fr;
    ret.sa += v.sa;
  });

  return ret ;
};


I hope this helps!

 -William

Brad Karels

unread,
Jun 22, 2012, 7:56:10 AM6/22/12
to mongod...@googlegroups.com
Thank you Scott and William - this adds clarity and got me over this hump!

I am still curious, however, as to why date.getDay() inside the reduce function returns "day of month" (e.g. 18 for 18-6-2012).  To William's point, this should be unnecessary, but it's still bugging me a bit.

Thank you both for your input - I appreciate your help.

Brad
Reply all
Reply to author
Forward
0 new messages