如何使用Map / Reduce MongoDB返回每个作者的总销售额

时间:2018-10-11 01:38:58

标签: mongodb

我在MongoDB中检查了Google的Map / Reduce函数,发现可以在单独的函数中完成每个阶段。但是,我尝试了它们,但没有一个起作用。

这是文档的示例。

  db.classes.insert({ 
        class : "Biology 101", 
        startDate : new Date(2016, 1, 11), 
        students : [ // Students info
        {fName : "Andy", lName : "Brennan", age : 36}, 
        {fName : "James", lName : "Hurley", age : 25},
         {fName : "Harry", lName : "Truman", age : 41} ], 
        cost : 1550,  // Cost per class
        professor : "Alice Jones", 
        topics : "Earth,Cell,Energy,Genetics,DNA", // Topics will be covered by the Professor. 
         book:[ // book info
        { Author: "Mike", title: "Holt McDougal Biology", sales: 9 },
        { Author: "Mike", title: "Holt McDougal Biology", sales: 10 }, 
        { Author: "Ryen", title: "Holt McDougal Biology", sales: 8 }]  })


        ----------
    I have 50 documents in a collection named "Classes", and I am applying Map/Reduce in MongoDB to return the total sales per each Author.
    I run the below code, but it throws an error message. 


----------


    db.runCommand(
       { group:
           {
             ns: 'classes',
             key: { 'book.price': 1, 'book.title': 1 },
             cond: {  },
             $reduce: function ( curr, result ) {
                         result.total += (curr.book.price * curr.book.Author.length);
                      },
             initial: { total : 0 }
           }
        }
    )


    ----------

    **The Output message in my terminal was as the following **

    "errmsg" : "Plan executor error during group command :: caused by :: Failed to invoke group reduce function:  :: caused by :: TypeError: curr.book.Author is undefined :\n$reduce@group reduce init:1:39\n@:1:177\n",
        "code" : 139,
        "codeName" : "JSInterpreterFailure"

Please, can anyone help to fix this code or to come up with a different Map/Reduce method?

1 个答案:

答案 0 :(得分:1)

您可以使用下面的map reduce。

var map = function() {
  this.book.forEach(function(val) {
      emit(val.Author,val);
   })
};

var reduce = function(key, values) {
    val = { count: 0, sales: 0 };
    values.forEach(function(value) {
        val.count += 1;
        val.sales += value.sales;
    })
    return val;
};

var finalize = function(key, val) {
    val.avg = val.sales/val.count;
    return val;
};

db.classes.mapReduce( map, reduce, { out: "map_ex_4", finalize:finalize  })