node.js - mapReduce not calling map nor reduce -
i started working mongodb , having troubles using mapreduce function. reason seems not calling map , reduce functions.
here code:
@getmonthlyreports: (req, res) -> app_id = req.app.id start = moment().subtract('years', 1).startof('month').unix() end = moment().endof('day').unix() console.log(start) console.log(end) map = -> geotriggers = 0 pushes = 0 console.log("ok") date = moment(@timestamp).startof('month').unix() campaign in @campaigns if campaign.geotriggers? geotriggers += campaign.geotriggers else if campaign.pushes? pushes += campaign.pushes emit date, geotriggers: geotriggers pushes: pushes reduce = (key, values) -> console.log("ok") geotriggers = 0 pushes = 0 value in values geotriggers += value.geotriggers pushes += value.pushes geotriggers: geotriggers pushes: pushes common.db.collection(req.app.id + "_daily_campaign_reports").mapreduce map, reduce, query: timestamp: $gte: start $lt: end out: inline: 1 , (err, results) -> console.log(results) responsehelper.returnmessage req, res, 200, results
i put console.logs , seems map , reduce functions not being called. results undefined.
is there missing?
apart how have commented on reason mapreduce failing due calling library function not exist on server (moment.js), not usage of mapreduce.
while mapreduce has it's uses, simple aggregation case better suited aggregation framework native c++ implementation opposed mapreduce runs inside javascript interpreter. result processing faster.
all need existing unix timestamp values start
, end
current day of month ( dayofmonth
) in order date math:
db.collection.aggregate([ // match documents using existing start , end values { "$match": { "timestamp": { "$gte": start, "$lt": end } }}, // unwind campaigns array { "$unwind": "$campaigns" }, // group on start of month value { "$group": { "_id": { "$subtract": [ "$timestamp", { "$mod": [ "$timestamp", 1000 * 60 * 60 * 24 * dayofmonth ] } ] }, "geotriggers": { "$sum": { "$cond": [ "$campaigns.geotriggers", 1, 0 ] } }, "pushes": { "$sum": { "$cond": [ "$campaigns.pushes", 1, 0 ] } }, }} ])
if reading code correctly have have each document containing array "campaigns", deal in aggregation framework use $unwind
pipeline stage expose each array member it's own document.
the date math done in $group
stage _id
key changing "timestamp" value equal starting date of month same thing code trying do. it's debatable use null
here range selection going result in singular date value, show date math possible.
with "unwound" array elements, process every element "for loop" , conditionally adds values "geotriggers" , "pushes" using $cond
operator. again presumes code these fields evaluate boolean true/false evaluation part of $cond
your query condition of course met $match
stage @ start of pipeline, using same range query.
that same thing without relying on additional libraries in server side processing , faster well.
see other aggregation framework operators reference.
Comments
Post a Comment