Stack Exchange
MapReduce in MongoDB - count by categories
I have a Mongo database with collection containing items like so:

This is my assignment:

Output example:

This is what I have so far but I'm really lost with mapreduce function
db.dvdrent.mapReduce(
   `function() {
      if(this.rental_date === null)
         return;

      if(this.film.categories === undefined)
         return;

      if(this.film.categories.length !== 1)
         return;

      var hour = {
            hour: (new Date(this.rental_date)).getHours()
        };

      emit(hour, this.film.categories[0].name);

   };`,
   `function(key,values) {
      var rv = {
         categories: [],
         films: 0
      };


      values.forEach(function(x) {

         if(typeof(x) === "string")
            rv.categories.push(x);
      });

      return rv;
   };`,
   {

   }
)


The question in the assignment snapshot is not clear enough, would be better if you write it out as plain text.

You don't necessarily need MapReduce to carry out such aggregation unless you have an explicit requirement to use it.
The following uses aggregation framework to carry out the aggregation which is much faster because it runs compiled C++ code, while MapReduce’s Javascript code is interpreted.
Consider this pipeline which gives the desired result (comments describing each pipeline step)
db.dvdrent.aggregate([
    // initial filter pipeline using $match
    { '$match': { 
        '$expr': {
            '$eq': [
                { '$size': '$film.categories' },
                1
            ]
        }
    } },

    // project a new field which holds the category name
    { '$addFields': {
        'category': { '$arrayElemAt': [ '$film.categories', 0 ] }
    } },

    // initial group - group by hour and category and aggregate counts
    { '$group': {
        '_id': {
            'hour': { 
                '$hour':  { 
                    '$dateFromString': {
                        'dateString': '$rental_date'
                    } 
                } 
            },
            'category': '$category.name'
        },
        'count': { '$sum': 1 }
    } },

    // second group - group documents from the previous group pipeline by the hour and create a lit of key/value documents
    { '$group': {
        '_id': '$_id.hour',
        'categories': {
            '$push': {
                'k': '$_id.category',
                'v': '$count'
            }
        }
    } },

    // convert the list of categories with counts documents to a key/value object/hash
    { '$project': {
        'categories': {
            '$arrayToObject': '$categories'
        }
    }}
])

