venerdì 18 settembre 2015

MongoDB - Script di MapReduce con uso di scope su map dinamico

Dovendo realizzare una MapReduce per il calcolo dei valori massimi e minimi in un determinato periodo (meteorologico) mi sono scontrato col il problema di passare ad una funzione di Map dei parametri dinamici provenienti da un ciclo.

Per risolvere questo problema bisogna utilizzare un parametro di scope quando si lancia l'esecuzione della MapReduce:


es:

var KEYS = {FIELD : 'test',PERIOD : 'Day'};

dbOne.rawdata.mapReduce(map,reduceMax,{out:{inline:1}, scope : {KEYS:KEYS}}).results;

e nella map posso usarlo:

var map = function(){


if(KEYS.PERIOD == 'Day')
...
emit(somefunction, this[KEYS.FIELD]);
...

};

esempio completo:



/***
Extract max a min data from rawtable of extracting data from La crosse WS1640
project: http://meteo.marcoberri.it
**/
var dbOne = db.getSisterDB('mbmeteolacrosse');
var periods = ['Hour','Day', 'Month', 'Year'];
for (var p in periods) {
var period =periods[p];
var fields = ['T1', 'H1', 'PRESS','WC', 'WS'];
for (var f in fields) {
var fieldName = fields[f];
var KEYS = {FIELD: fieldName, PERIOD: period};
var map = function(){
var periodFunction = "";
var day = (this.ts.getDate() <10 ? "0" + this.ts.getDate() : this.ts.getDate());
var month = (this.ts.getMonth()+1 < 10 ? "0" + (this.ts.getMonth()+1) : (this.ts.getMonth()+1));
if(KEYS.PERIOD == 'Hour')
periodFunction = (this.ts.getFullYear() + "-" + month + "-" + day + ":"+ (this.ts.getHours()<10 ? "0"+this.ts.getHours() : this.ts.getHours()) );
if(KEYS.PERIOD == 'Day')
periodFunction = (this.ts.getFullYear() + "-" + month + "-" + day );
if(KEYS.PERIOD == 'Month')
periodFunction = (this.ts.getFullYear() + "-" + month);
if(KEYS.PERIOD == 'Year')
periodFunction = this.ts.getFullYear();
emit(periodFunction, this[KEYS.FIELD]);
};
var reduceMin = function(date, values){
var min = values[0];
values.forEach(
function(val) {
if(!isNaN(val) && val < min)
min = val;
}
);
return min
};
var reduceMax = function(date, values){
var max = values[0];
values.forEach(
function(val) {
if(!isNaN(val) && val > max)
max = val;
}
);
return max
};
var c = dbOne.rawdata.mapReduce(map,reduceMin,{out:{inline:1}, scope : {KEYS:KEYS}}).results;
var fname = fieldName + 'Min' + period;
for(var i=0;i<c.length;i++){
var updateDate = {};
updateDate["$set"] = {}
updateDate["$set"][fname] = c[i].value;
updateDate["$set"]['ts'] = c[i]._id;
dbOne.maxmindata.update({'ts' : c[i]._id},updateDate,{'upsert':true});
};
var c = dbOne.rawdata.mapReduce(map,reduceMax,{out:{inline:1}, scope : {KEYS:KEYS}}).results;
var fname = fieldName + 'Max' + period;
for(var i=0;i<c.length;i++){
var updateDate = {};
updateDate["$set"] = {}
updateDate["$set"][fname] = c[i].value;
updateDate["$set"]['ts'] = c[i]._id;
dbOne.maxmindata.update({'ts' : c[i]._id},updateDate,{'upsert':true});
};
print(fieldName + " - for:" + period +" --> ok");
};
};
view raw MaxMinData.js hosted with ❤ by GitHub

Nessun commento: