Visualizzazione post con etichetta MapReduce. Mostra tutti i post
Visualizzazione post con etichetta MapReduce. Mostra tutti i post

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:



venerdì 28 dicembre 2012

MongoDB - MapReduce - Max e Min nel periodo

Utilizzo la piccola app del Meteo per fare qualche esperimento con le Map/Reduce
Devo ottenere il valore massimo e minino dei valori giornalieri, mensili e annuali da una collection contentente i logger raccolti ogni 5 minuti.

la collection sorgente (Meteolog):

{ "_id" : ObjectId("50d5a8a01e05acfe08c086fb"), "className" : "it.marcoberri.mbmeteo.model.Meteolog" , "n" : 1643, "time" : ISODate("2012-12-09T00:33:00Z"), "interval" : 5, "indoorHumidity" : 65, "indo orTemperature" : 19.5, "outdoorHumidity" : 72, "outdoorTemperature" : -0.6, "absolutePressure" : 997 .2, "wind" : 0, "gust" : 0.3, "direction" : "SE", "relativePressure" : 1025, "dewpoint" : -5, "windc hill" : -0.6, "hourRainfall" : 0, "dayRainfall" : 6.9, "weekRainfall" : 12.3, "monthRainfall" : 12.3 , "totalRainfall" : 12.3, "windLevel" : 0, "gustLevel" : 1 }

{ "_id" : ObjectId("50d5a8a01e05acfe08c086fc"), "className" : "it.marcoberri.mbmeteo.model.Meteolog" , "n" : 1644, "time" : ISODate("2012-12-09T00:38:00Z"), "interval" : 5, "indoorHumidity" : 65, "indo orTemperature" : 19.5, "outdoorHumidity" : 71, "outdoorTemperature" : -0.8, "absolutePressure" : 997 .3, "wind" : 0.3, "gust" : 0.7, "direction" : "S", "relativePressure" : 1025.1, "dewpoint" : -5.4, " windchill" : -0.8, "hourRainfall" : 0, "dayRainfall" : 6.9, "weekRainfall" : 12.3, "monthRainfall" : 12.3, "totalRainfall" : 12.3, "windLevel" : 1, "gustLevel" : 1 }
etc.


la funzionalità di map sul singolo giorno (variabile time_short)

map = function(){
    var fields =['outdoorTemperature','outdoorHumidity','absolutePressure','relativePressure','wind','gust','dewpoint','windchill',

'hourRainfall','dayRainfall','weekRainfall','monthRainfall','totalRainfall','windLevel','gustLevel'];

 var objs = {};

 for( var f=0; f<fields.length;f++) {
  var k = fields[f];
  objs[k] = { "min" : this[k], "max" : this[k]};
 }

 var time_short = this.time.getFullYear() + "-" + this.time.getMonth() + "-" + this.time.getDate();
 emit(time_short,objs)
}



La funzionalità di reduce:

reduce = function(key, values){
   var fields =['outdoorTemperature','outdoorHumidity','absolutePressure','relativePressure','wind','gust','dewpoint','windchill',

'hourRainfall','dayRainfall','weekRainfall','monthRainfall','totalRainfall','windLevel','gustLevel'];
   var res = values[0];
    for ( var i=1; i<values.length; i++ ) {
 for( var f=0; f<fields.length;f++) {
  var k = fields[f];
  var v = values[i][k];
         if ( v.min < res[k].min  )
            res[k].min = v.min;
         if ( v.max  > res[k].max  )
                   res[k].max = v.max;
 }
    }
    return res;
}


Usiamo le funzionalità:

db.Meteolog.mapReduce(map,reduce,{out:{merge:"reduceMaxMinDay"}});
db.reduceMaxMinDay.find();

result:

{ "_id" : "2012-11-23", "value" : { "outdoorTemperature" : { "min" : -2.3, "max" : 5.6 }, "outdoorHu midity" : { "min" : 79, "max" : 90 }, "absolutePressure" : { "min" : 996.8, "max" : 999 }, "relative Pressure" : { "min" : 1024.6, "max" : 1026.8 }, "wind" : { "min" : 0, "max" : 0.7 }, "gust" : { "min " : 0, "max" : 1 }, "dewpoint" : { "min" : -4.7, "max" : 2.4 }, "windchill" : { "min" : -2.3, "max" : 5.6 }, "hourRainfall" : { "min" : 0, "max" : 0 }, "dayRainfall" : { "min" : 0, "max" : 0 }, "weekR ainfall" : { "min" : 0, "max" : 0 }, "monthRainfall" : { "min" : 4.2, "max" : 4.2 }, "totalRainfall" : { "min" : 4.2, "max" : 4.2 }, "windLevel" : { "min" : 0, "max" : 1 }, "gustLevel" : { "min" : 0, "max" : 1 } } }

{ "_id" : "2012-11-9", "value" : { "outdoorTemperature" : { "min" : -2.3, "max" : 13.4 }, "outdoorHu midity" : { "min" : 26, "max" : 75 }, "absolutePressure" : { "min" : 992.9, "max" : 999.4 }, "relati vePressure" : { "min" : 1020.7, "max" : 1027.2 }, "wind" : { "min" : 0, "max" : 1 }, "gust" : { "min " : 0, "max" : 1.7 }, "dewpoint" : { "min" : -7.3, "max" : 0.3 }, "windchill" : { "min" : -2.3, "max " : 13.4 }, "hourRainfall" : { "min" : 0, "max" : 8.1 }, "dayRainfall" : { "min" : 0, "max" : 12.3 } , "weekRainfall" : { "min" : 0, "max" : 20.4 }, "monthRainfall" : { "min" : 0, "max" : 20.4 }, "tota lRainfall" : { "min" : 0, "max" : 20.4 }, "windLevel" : { "min" : 0, "max" : 1 }, "gustLevel" : { "m in" : 0, "max" : 2 } } } etc.

per modificare il periodo di calcolo basta modficare la variabile che permette il raggruppamento delle info:
es: mesile --> var time_short = this.time.getFullYear() + "-" + this.time.getMonth();
es: annulale -->  var time_short = this.time.getFullYear();