/** * 处理map reduce统计 * * @return string */ public function mrAction() { $cache = $this->cache(); $this->_worker->addFunction("mapreduce", function (\GearmanJob $job) use($cache) { try { $job->handle(); $params = unserialize($job->workload()); $out = $params['out']; $this->_data->setCollection($params['dataCollection']); $this->_data->setReadPreference(\MongoClient::RP_SECONDARY_PREFERRED); $dataModel = $this->_data; $statisticInfo = $params['statisticInfo']; $query = $params['query']; $method = $params['method']; $rst = mapReduce($out, $dataModel, $statisticInfo, $query, $method); var_dump($rst); $cache->remove($out); if (is_array($rst) && isset($rst['ok']) && $rst['ok'] === 0) { switch ($rst['code']) { case 500: $job->sendWarning('根据查询条件,未检测到有效的统计数据'); break; case 501: $job->sendWarning('MapReduce执行失败,原因:' . $rst['msg']); break; case 502: $job->sendWarning('程序正在执行中,请勿频繁尝试'); break; case 503: $job->sendWarning('程序异常:' . $rst['msg']); break; } $job->sendFail(); return false; } // sleep(30);//成功的操作等待30秒,用以确保复制集完成同步 $job->sendComplete('Complete'); return true; } catch (\Exception $e) { var_dump(exceptionMsg($e)); $job->sendException(exceptionMsg($e)); } }); while ($this->_worker->work()) { if ($this->_worker->returnCode() != GEARMAN_SUCCESS) { echo "return_code: " . $this->_worker->returnCode() . "\n"; } } return $this->response; }
/** * 逐一统计所有需要统计的脚本信息 * 脚本执行方法: php index.php dashboard run * * @throws \Exception */ public function runAction() { $logError = function ($statisticInfo, $rst) { $this->_statistic->update(array('_id' => $statisticInfo['_id']), array('$set' => array('dashboardOut' => '', 'dashboardError' => is_string($rst) ? $rst : Json::encode($rst)))); }; $statistics = $this->_statistic->findAll(array('resultExpireTime' => array('$lte' => new \MongoDate()))); if (empty($statistics)) { echo 'empty'; return $this->response; } foreach ($statistics as $statisticInfo) { try { if (!empty($statisticInfo['dashboardOut'])) { $oldDashboardOut = $this->collection($statisticInfo['dashboardOut'], DB_MAPREDUCE, DEFAULT_CLUSTER); $oldDashboardOut->physicalDrop(); } //检查是否存在映射关系 $mapCollection = $this->_mapping->findOne(array('collection_id' => $statisticInfo['collection_id'], 'active' => true)); if ($mapCollection != null) { $dataModel = $this->collection($mapCollection['collection'], $mapCollection['database'], $mapCollection['cluster']); } else { $dataModel = $this->collection(iCollectionName($statisticInfo['collection_id'])); } $query = array(); if (!empty($statisticInfo['dashboardQuery'])) { $query['$and'][] = $statisticInfo['dashboardQuery']; } $query['$and'][] = array('__CREATE_TIME__' => array('$gte' => new \MongoDate(time() - $statisticInfo['statisticPeriod']))); $rst = mapReduce($dataModel, $statisticInfo, $query, 'reduce'); if ($rst instanceof \MongoCollection) { $outCollectionName = $rst->getName(); // 输出集合名称 $this->_statistic->update(array('_id' => $statisticInfo['_id']), array('$set' => array('dashboardOut' => $outCollectionName, 'lastExecuteTime' => new \MongoDate(), 'resultExpireTime' => new \MongoDate(time() + $statisticInfo['interval'])))); } else { $logError($statisticInfo, $rst); } } catch (\Exception $e) { $logError($statisticInfo, $e->getMessage()); } } echo 'OK'; return $this->response; }
/** * 测试结果 * * @return \Zend\Stdlib\ResponseInterface */ public function testAction() { $statistic_id = $this->params()->fromQuery('statistic_id', null); $logError = function ($statisticInfo, $rst) { $this->_statistic->update(array('_id' => $statisticInfo['_id']), array('$set' => array('dashboardOut' => '', 'dashboardError' => is_string($rst) ? $rst : Json::encode($rst)))); }; $statistics = $this->_statistic->findAll(array('_id' => myMongoId($statistic_id), 'isDashboard' => true)); if (empty($statistics)) { echo 'empty'; return $this->response; } foreach ($statistics as $statisticInfo) { try { if (!empty($statisticInfo['dashboardOut'])) { $oldDashboardOut = $this->collection($statisticInfo['dashboardOut'], DB_MAPREDUCE, DEFAULT_CLUSTER); $oldDashboardOut->physicalDrop(); } // 检查是否存在映射关系 $mapCollection = $this->_mapping->findOne(array('collection_id' => $statisticInfo['collection_id'], 'active' => true)); if ($mapCollection != null) { $dataModel = $this->collection()->secondary($mapCollection['collection'], $mapCollection['database'], $mapCollection['cluster']); } else { $dataModel = $this->collection()->secondary(iCollectionName($statisticInfo['collection_id'])); } $query = array(); if (!empty($statisticInfo['dashboardQuery'])) { $query['$and'][] = $statisticInfo['dashboardQuery']; } $query['$and'][] = array('__CREATE_TIME__' => array('$gte' => new \MongoDate(time() - $statisticInfo['statisticPeriod']))); $out = 'dashboard_' . $statisticInfo['_id']->__toString(); $rst = mapReduce($out, $dataModel, $statisticInfo, $query, 'replace'); if ($rst instanceof \MongoCollection) { $outCollectionName = $rst->getName(); // 输出集合名称 $this->_statistic->update(array('_id' => $statisticInfo['_id']), array('$set' => array('dashboardOut' => $outCollectionName, 'lastExecuteTime' => new \MongoDate(), 'resultExpireTime' => new \MongoDate(time() + $statisticInfo['interval'])))); } else { $logError($statisticInfo, $rst); } // 替换统计结果中的数据为人可读数据开始 if (isset($statisticInfo['xAxisType']) && $statisticInfo['xAxisType'] === 'value') { $rshDatas = $this->dealRshData($statisticInfo['project_id'], $statisticInfo['collection_id'], $statisticInfo['xAxisField']); if (!empty($rshDatas)) { try { $rstModel = $this->collection($out, DB_MAPREDUCE, DEFAULT_CLUSTER); $rstModel->setNoAppendQuery(true); $cursor = $rstModel->find(array()); while ($cursor->hasNext()) { $row = $cursor->getNext(); $rstModel->physicalRemove(array('_id' => $row['_id'])); $_id = $row['_id']; $rstModel->update(array('_id' => isset($rshDatas[$_id]) ? $rshDatas[$_id] : $_id), array('$set' => array('value' => $row['value'])), array('upsert' => true)); } } catch (\Exception $e) { var_dump($e); } } } // 替换统计结果中的数据为人可读数据结束 } catch (\Exception $e) { $logError($statisticInfo, $e->getMessage()); } } echo 'OK'; return $this->response; }
/** * 对集合数据进行统计 * 目前支持的统计类型: * 计数、唯一数、求和、均值、中位数、方差、标准差、最大值、最小值 * * @author young * @name 对集合数据进行统计 * @version 2014.01.29 young */ public function statisticAction() { $action = $this->params()->fromQuery('action', null); $export = filter_var($this->params()->fromQuery('export', false)); $statistic_id = $this->params()->fromQuery('__STATISTIC_ID__', null); if ($action !== 'statistic') { return $this->msg(false, '$action is not statistic'); } if (empty($statistic_id)) { throw new \Exception('请选择统计方法'); } $statisticInfo = $this->_statistic->findOne(array('_id' => myMongoId($statistic_id))); if ($statisticInfo == null) { throw new \Exception('统计方法不存在'); } try { $query = array(); $query = $this->searchCondition(); $rst = mapReduce($this->_data, $statisticInfo, $query); if (is_array($rst) && isset($rst['ok']) && $rst['ok'] === 0) { switch ($rst['code']) { case 500: return $this->deny('根据查询条件,未检测到有效的统计数据'); break; case 501: return $this->deny('MapReduce执行失败,原因:' . $rst['msg']); break; case 502: return $this->deny('程序正在执行中,请勿频繁尝试'); break; case 503: return $this->deny('程序异常:' . $rst['msg']); break; } } if (!$rst instanceof \MongoCollection) { return $this->deny('$rst不是MongoCollection的子类实例'); throw new \Exception('$rst不是MongoCollection的子类实例'); } $outCollectionName = $rst->getName(); // 输出集合名称 if ($export) { $datas = $rst->findAll(array()); $excel = array(); $excel['title'] = array('键', '值'); $excel['result'] = $datas; arrayToExcel($excel); } else { $limit = intval($statisticInfo['maxShowNumber']) > 0 ? intval($statisticInfo['maxShowNumber']) : 100; $datas = $rst->findAll(array(), array('value' => -1), 0, $limit); return $this->rst($datas, 0, true); } } catch (\Exception $e) { return $this->deny('程序异常:' . $e->getLine() . $e->getMessage()); } }