Exemplo n.º 1
0
/**
 * map reduce统一处理函数
 *
 * @param string $out            
 * @param resource $dataModel            
 * @param array $statisticInfo            
 * @param array $query            
 * @param string $method            
 * @param string $scope            
 * @param array $sort            
 * @param int $limit            
 */
function mapReduce($out = null, MongoCollection $dataModel, $statisticInfo, $query, $method = 'replace', $scope = null, $sort = array('$natural' => 1), $limit = null)
{
    $map = "function(){\r\n            var xAxisType = '{$statisticInfo['xAxisType']}';\r\n            var xAxisField = this.{$statisticInfo['xAxisField']};  \r\n            var yAxisField = this.{$statisticInfo['yAxisField']};  \r\n            var xAxisTitle = '{$statisticInfo['xAxisTitle']}'; \r\n            var key = '';\r\n            var rst = {\r\n               total : isNumber(yAxisField) ? yAxisField : 0,\r\n               count : yAxisField!==null ? 1 : 0,\r\n               max : isNumber(yAxisField) ? yAxisField : Number.NEGATIVE_INFINITY,\r\n               min : isNumber(yAxisField) ? yAxisField : Number.POSITIVE_INFINITY,\r\n               val : [yAxisField]\r\n            };\r\n\r\n            if(xAxisField==null ||yAxisField==null) {\r\n                key = '__OTHERS__';\r\n                return emit(key,rst);\r\n            }\r\n            if(xAxisType=='hour' || xAxisType=='day' || xAxisType=='month' || xAxisType=='year') {\r\n                if(xAxisField!==null) {\r\n                    try {\r\n                        var time = new Date(xAxisField);\r\n                        var timeSec = time.getTime();\r\n                        var year = time.getFullYear();\r\n                        var m = time.getMonth() + 1;\r\n                        var month = m<10 ? '0'+m : m; \r\n                        var d = time.getDate();\r\n                        var day = d<10 ? '0'+d : d; \r\n                        var h = time.getHours();\r\n                        var hour = h<10 ? '0'+h : h; \r\n                    } catch (e) {\r\n                        key = '__OTHERS__';\r\n                        return emit(key,rst);\r\n                    }\r\n                }\r\n                else {\r\n                    key = '__OTHERS__';\r\n                    return emit(key,rst);\r\n                }\r\n            }\r\n            else {\r\n                if(!isNumber(yAxisField)) {\r\n                    yAxisField = 0;\r\n                }\r\n            }\r\n            \r\n            if(xAxisField instanceof Array || xAxisField instanceof Object) {\r\n                if(xAxisField instanceof NumberLong) {\r\n                    xAxisField = NumberInt(xAxisField);\r\n                } else {\r\n                    xAxisField = xAxisField.toString();\r\n                }\r\n            }\r\n            \r\n            switch(xAxisType) {\r\n                case 'total':\r\n                     key = xAxisTitle;\r\n                     break;\r\n                case 'range':\r\n                    var\toptions = [\r\n                        0,\r\n\t\t\t\t\t\t10, 20, 50,\r\n\t\t\t\t\t\t100, 200, 500,\r\n\t\t\t\t\t\t1000, 2000, 5000,\r\n\t\t\t\t\t\t10000, 20000, 50000,\r\n\t\t\t\t\t\t100000, 200000, 500000,\r\n\t\t\t\t\t\t1000000, 2000000, 5000000,\r\n\t\t\t\t\t\t10000000, 20000000, 50000000,\r\n\t\t\t\t\t\t100000000, 200000000, 500000000,\r\n\t\t\t\t\t\t1000000000, Number.POSITIVE_INFINITY\r\n\t\t\t\t\t];\r\n    \t\t\t\t\r\n\t\t\t\t\tfor(var index = 0; options[index] < field; index++) {\r\n\t\t\t\t\t\tkey = options[index]+'-'+options[index+1];\r\n\t\t\t\t\t}\r\n                    break;\r\n                case 'day':\r\n                    key = year+'/'+month+'/'+day;\r\n                    break;\r\n                case 'month':\r\n                    key = year+'/'+month;\r\n                    break;\r\n                case 'year':\r\n                    key = year;\r\n                    break;\r\n                case 'hour':\r\n                    key = hour;\r\n                    break;\r\n                default : \r\n                    key = xAxisField;\r\n                    break;\r\n            }\r\n            \r\n            return emit(key,rst);\r\n        }";
    $reduce = "function(key,values){\r\n              var rst = {\r\n                   total : 0,\r\n                   count : 0,\r\n                   max : Number.NEGATIVE_INFINITY,\r\n                   min : Number.POSITIVE_INFINITY,\r\n                   val : []\r\n              };\r\n\r\n              var yAxisType = '{$statisticInfo['yAxisType']}';\r\n              var length = values.length;\r\n              for(var idx = 0; idx < length ; idx++) {  \r\n                  if(yAxisType=='count') {\r\n                      rst.count += values[idx].count;\r\n                  } else if(yAxisType=='sum') {\r\n                      rst.total += values[idx].total;\r\n                  } else if(yAxisType=='max') {\r\n                      if(rst.max==null)\r\n                          rst.max = values[idx].max;\r\n                      else if(rst.max <= values[idx].max) {\r\n                          rst.max = values[idx].max;\r\n                      }\r\n                  } else if(yAxisType=='min') {\r\n                      if(rst.min==null) {\r\n                          rst.min = values[idx].min;\r\n                      }\r\n                      else if(rst.min >= values[idx].min) {\r\n                          rst.min = values[idx].min;\r\n                      }\r\n                  } else if(yAxisType=='unique'||yAxisType=='distinct') {\r\n                      if(values[idx].val instanceof Array) {\r\n                          values[idx].val.forEach(function(v,i){\r\n                              rst.val.push(v);\r\n                          });   \r\n                      }\r\n                  } else if(yAxisType=='avg') {\r\n                      rst.total += values[idx].total;\r\n                      rst.count += values[idx].count;\r\n                  } else if(yAxisType=='median') {\r\n                      values[idx].val.forEach(function(v,i){\r\n                          if(typeof(v)=='number') {\r\n                              rst.val.push(v);\r\n                          }\r\n                      });\r\n                  } else if(yAxisType=='variance') {\r\n                      rst.total += values[idx].total;\r\n                      rst.count += values[idx].count;\r\n                      values[idx].val.forEach(function(v,i){\r\n                          rst.val.push(v);\r\n                      });\r\n                  } else if(yAxisType=='standard') {\r\n                      rst.total += values[idx].total;\r\n                      rst.count += values[idx].count;\r\n                      values[idx].val.forEach(function(v,i){\r\n                          rst.val.push(v);\r\n                      });\r\n                  }\r\n              }\r\n              return rst;\r\n        }";
    $finalize = "function(key,reducedValue){\r\n            var rst = 0;\r\n            var uniqueData = [];\r\n            var uniqueNumber = 0;\r\n            var yAxisType = '{$statisticInfo['yAxisType']}';  \r\n            if(yAxisType=='count') {\r\n                rst = reducedValue.count;\r\n            }\r\n            else if(yAxisType=='sum') {\r\n                rst = reducedValue.total;\r\n            }\r\n            else if(yAxisType=='max') {\r\n                rst = reducedValue.max;\r\n            }\r\n            else if(yAxisType=='min') {\r\n                rst = reducedValue.min;\r\n            }\r\n            else if(yAxisType=='unique' || yAxisType=='distinct') {\r\n                reducedValue.val.forEach(function(v,i){\r\n                    if(uniqueData.indexOf(v)===-1) {\r\n                        uniqueNumber += 1;\r\n                        uniqueData.push(v);\r\n                    }\r\n                });\r\n                rst = uniqueNumber;\r\n            }\r\n            else if(yAxisType=='avg') {\r\n                rst = reducedValue.total / reducedValue.count;\r\n                rst = Math.round(rst*10000)/10000;\r\n            }\r\n            else if(yAxisType=='median') {\r\n                reducedValue.val.sort(function(a,b){return a>b?1:-1});\r\n                var length = reducedValue.val.length;\r\n                rst = reducedValue.val[parseInt(Math.floor(length/2))];\r\n            }\r\n            else if(yAxisType=='variance') {\r\n                var avg = reducedValue.total / reducedValue.count;\r\n                var squared_Diff = 0;\r\n                var length = reducedValue.val.length;\r\n                for(var i=0;i<length;i++) {\r\n                    var deviation = reducedValue.val[i] - avg;\r\n                    squared_Diff += deviation * deviation;\r\n                }\r\n                rst = squared_Diff/length;\r\n                rst = Math.round(rst*10000)/10000;\r\n            }\r\n            else if(yAxisType=='standard') {\r\n                var avg = reducedValue.total / reducedValue.count;\r\n                var squared_Diff = 0;\r\n                var length = reducedValue.val.length;\r\n                for(var i=0;i<length;i++) {\r\n                    var deviation = reducedValue.val[i] - avg;\r\n                    squared_Diff += deviation * deviation;\r\n                }\r\n                rst = Math.sqrt(squared_Diff/length);\r\n                rst = Math.round(rst*10000)/10000;\r\n            }\r\n            return rst;\r\n        }";
    return $dataModel->mapReduce($out, $map, $reduce, $query, $finalize, $method, $scope, $sort, $limit);
}