<?php/***mongo类*User:wujp<wujp@nalashop.com>*Date:13-10-12*Time:下午5:48*/classMongo_DB{#链接public$conn=null;#mongodbpublic$db=null;#链接参数private$url='';#判断db是否链接private$collected=null;#查询、更新映射有|private$four_map=array(#值是字符串,值不用处理'>'=>'$gt','>='=>'$gte','<'=>'$le','<='=>'$lte','!='=>'$ne','@'=>'$exists',#键是否存在'?'=>'perl',#正则);private$ele_map=array(#数组,值需要处理'~'=>'$elemMatch'#内嵌文档);private$log_map=array(#值必须是数组'^'=>'$in','!^'=>'$nin','*'=>'$all',#指定数组元素);#没有|private$lgi_map=array(#必须是二维数组'$'=>'$or','&'=>'$and',);private$where_map=array('%'=>'$where',#javascript函数);private$sort_map=array('DESC'=>-1,'ASC'=>1);#当前db下所有集合=>键数组public$collections=null;#基本配置参数private$config=array('host'=>'localhost','port'=>'27017','dbname'=>'','user'=>'','pass'=>'','logpath'=>'',#日志目录'replicaset'=>array(#集群'host'=>array()//'host'=>array('host:port'),#主机群//'options'=>array('readPreference','readPreferenceTags','replicaSet','slaveok')),);/***构造函数,基本参数设置*@param$config**/publicfunction__construct($config){if(is_array($config)&&$config){foreach($this->configas$k=>$v){if(isset($config[$k])&&$config[$k])$this->config[$k]=!is_array($config[$k])?trim($config[$k]):$config[$k];}$this->connect();}}/***初始化mongo**/privatefunctionconnect(){if(!extension_loaded('mongo'))exit('ERROR:MONGOEXTENSIONNOTLOAD');if($this->conn===NULL){try{if($this->config['replicaset']['host']){#todo主从配置,或者副本集,读扩展,}else{$this->url.="mongodb://{$this->config['user']}:{$this->config['pass']}@{$this->config['host']}:{$this->config['port']}/{$this->config['dbname']}";$this->conn=newMongoClient($this->url);}$this->db=$this->conn->selectDB($this->config['dbname']);if($this->db){$this->collected=true;$this->GetAllCollection();#获取所有集合列表}}catch(MongoConnectionException$e){$this->ErrLog($e->getMessage());exit('MONGOCONNECTERROR');}}}/***析构函数*/publicfunction__destruct(){$this->collected=$this->collections=$this->db=$this->conn=null;}/***获取db下所有集合名称**@internalparam$dbname*@returnbool*/privatefunctionGetAllCollection(){if(!$this->collected)returnfalse;$colls=$this->db->listCollections();if($colls){foreach($collsas$v){$pos=strpos($v,$this->config['dbname']);if($pos!==false)$this->collections[]=substr($v,($pos+strlen($this->config['dbname'])+1));}returntrue;}else{returnfalse;}}/***初始化集合对象*@param$collname集合名*@returnmixed*/publicfunctionGetMonCollection($collname){if(!$this->collected)returnfalse;return$this->db->selectCollection($collname);}/***转换字符编码*@param$array*@returnbool*/privatefunctionConvertEncode($array){if(is_array($array)){foreach($arrayas&$v){if(is_array($v)){$v=$this->ConvertEncode($v);if(!$v)returnfalse;}else{$code=mb_detect_encoding($v,array('UTF-8','ASCII','GB2312','GBK','CP936'),true);if($code!=='UTF-8')$v=mb_convert_encoding($v,'UTF-8',$code);}}return$array;}returnfalse;}/***获取where参数*@param$where*@parambool$type*@returnstring**/privatefunctionGetWhere($where,$type=false){$wheres=array();$maps=array('four_map','log_map','ele_map');$maps_np=array_merge($this->lgi_map,$this->where_map);if(is_array($where)&&$where){#过滤查询条件foreach($whereas$field=>$val){$pos=strpos($field,'|');if($pos!==false){#四则、正则、函数、数组、in、多重条件内嵌文档$tep=substr($field,0,$pos);$key=substr($field,($pos+1));if($key!==false){foreach($mapsas$v){$arr=$this->$v;if(in_array($tep,array_keys($arr))){if($v=='ele_map'&&is_array($val))$val=$this->GetWhere($val,true);if($tep=='?'){#正则$val=newMongoRegex($val);$wheres[$key]=$val;}else{$wheres[$key][$arr[$tep]]=$val;}}}}}elseif(in_array($field,array_keys($maps_np))){if(in_array($field,array_keys($this->lgi_map))&&is_array($val)){#逻辑foreach($valas$v){$val=$this->GetWhere($v,true);$wheres[$maps_np[$field]][]=$val;}}else{$wheres[$maps_np[$field]]=$val;}}else{#普通查询、单一条件内嵌文档if(strpos($field,"[")!==false)$field=str_replace("[",".",$field);if(is_array($val)&&$type){$arr=$this->GetWhere($val);foreach($arras$k=>$v){$wheres[$k][]=$v;}}elseif(is_null($val)){$wheres[$field]=array('$in'=>array(null),'$exists'=>1);}else{$wheres[$field]=$val;#支持array('age'=>array('>'=>'18','<='=>'20'))}}}}return$wheres;}/***插入一行*@param$collect*@param$value*@returnbool*/publicfunctionInsOne($collect,$value){if(!$this->collected||!is_array($value))returnfalse;$id=array_search('id',array_keys($value));#处理有id字段的情况if($id!==false&&array_search('_id',array_keys($value))===false){$value['_id']=$value['id'];unset($value['id']);}$value=$this->ConvertEncode($value);if(!$value)returnfalse;try{$result=$this->GetMonCollection($collect)->insert($value);$result=$result['err']?false:true;}catch(MongoException$e){$this->ErrLog($e->getMessage());returnfalse;}return$result;}/***插入多行*@param$collect集合*@param$fields*@param$values键值对:array(0=>array(''=>''))*@parambool$continueOnError是否忽略插入错误,默认忽略*@returnbool*/publicfunctionInsMulit($collect,$fields,$values,$continueOnError=false){if(!is_array($fields)||!is_array($values)||!$this->collected)returnfalse;$id=array_search('id',$fields);#处理有id字段的情况if($id!==false&&array_search('_id',$fields)===false)$fields[$id]='_id';$data=array();$values=$this->ConvertEncode($values);if($values){foreach($valuesas$v){if(is_array($v)){$v=array_combine($fields,$v);if($v)$data[]=$v;}}}if(!$data)returnfalse;$option['continueOnError']=$continueOnError?true:false;try{$result=$this->GetMonCollection($collect)->batchinsert($data,$option);$result=$result['err']?false:true;}catch(MongoException$e){$this->ErrLog($e->getMessage());returnfalse;}return$result;}/***查询一个*@param$collect*@paramarray$where*@param$fieldstring*@returnbool*/functionFindOne($collect,$where=array(),$field){if(!$this->collected)returnfalse;$wheres=$this->GetWhere($where);if($where&&!$wheres)returnfalse;if(is_string($field)&&trim($field))$field=trim($field);elsereturnfalse;$result=$this->GetMonCollection($collect)->findOne($wheres,array($field));if($result){$arr=get_object_vars($result['_id']);$result['_id']=$arr['$id'];return$result[$field];}returnfalse;}/***查询一条*@param$collect*@paramarray|string$where*@paramarray$fields*@paramstring$type*@returnarray|bool*/functionFindRow($collect,$where=array(),$fields=array(),$type='assoc'){if(!$this->collected)returnfalse;$wheres=$this->GetWhere($where);if($where&&!$wheres)returnfalse;if($fields&&is_array($fields)){#过滤fields$val='';for($i=0;$i<count($fields);$i++){$val[]=1;}$fields=array_combine($fields,$val);}else{$fields=array();}$result=$this->GetMonCollection($collect)->findOne($wheres,$fields);if($result){if(in_array('_id',$fields)){$arr=get_object_vars($result['_id']);$result['_id']=$arr['$id'];}else{unset($result['_id']);}if(strtolower($type)=='array')$result=array_values($result);return$result;}returnfalse;}/***复合查询todo查询高级选项扩展snapshotmaxscanminmaxhintexplain*<-----------------------*$gt:>|$gte:>=|$le:<|$lte:<=|$ne:!=*array('x'=>array('$gt'=>'20'))**$or:$|$end:&*array('x'=>array('$in'=>array('1','2')))**$where:%*array('x'=>array('$where'=>function))**正则表达式:*?**数组:*$all:***内嵌文档:*单个条件:username.userusername[user*多个条件:$elemMatch**逻辑操作符:*not:!*or:$*end:&*sort*array('x'=>0)**limit|skip*$where=array('&|'=>array('she_hash'=>'48b6c531ef2469469ede4ac21eebcf51','type'=>'doing'));*$field=array('time','_id'=>0);*$res=$mongo->FindMix('sapilog',$where,$field,'1,2',array('time'=>'desc'));*------------------------->*@param$collect|string*@paramstring$where|arrayarray('>|x'=>'10','<=|x'=>'20','^|x'=>array(),'%|x'=>'fun')*@paramarray|string$fields|array|string返回字段默认为全部字符串返回一个字段,键为数字则为返回该字段,键为字段,值为-1为不返回该字段*@paramstring$limit|stringskip,limit0,10如果没有默认skip为0limit为当前变量*@paramstring$sort|arrayarray('x'=>'desc|asc')desc=>-1asc=>*@paramstring$type|string返回类型默认为关联数组assoc|array*@returnbool*/publicfunctionFindMix($collect,$where='',$fields=array(),$limit='',$sort='',$type='assoc'){if(!$this->collected)returnfalse;$wheres=$this->GetWhere($where);if($where&&!$wheres)returnfalse;if($fields&&is_array($fields)){#过滤fields$val='';for($i=0;$i<count($fields);$i++){$val[]=1;}$fields=array_combine($fields,$val);}else{$fields=array();}$limits='';$skip='';if(is_string($limit)){#过滤limit$limit=explode(",",trim($limit));if($limit&&is_numeric(implode('',$limit))){if(count($limit)==1){$limits=$limit[0];}else{$skip=$limit[0];$limits=$limit[1];}}}elseif(is_numeric($limit)){$limits=trim($limit);}$sorts='';if(is_array($sort)&&$sort){#过滤sortforeach($sortas$k=>$v){$k=trim($k);$v=strtoupper(trim($v));if(in_array($v,array_keys($this->sort_map))){$sorts[$k]=$this->sort_map[$v];}}}$result=$this->GetMonCollection($collect)->find($wheres,$fields);if($skip)$result=$result->skip($skip);if($limits)$result=$result->limit($limits);if($sorts)$result=$result->sort($sorts);if($result){$return=array();foreach($resultas$v){$return[]=$v;}foreach($returnas&$v){if(in_array('_id',$fields)){$arr=get_object_vars($v['_id']);$v['_id']=$arr['$id'];}else{unset($v['_id']);}if(strtolower($type)=='array')$v=array_values($v);}return$return;}returnfalse;}/***修改记录*$inc、$set、$unset修改普通文档,如果有就修改,没有就条件加值创建,前者只支持数字类型,使用后者,$unset删除元素*$push、$addToSet添加数组元素,前者不去重,使用后者*$pop、$pull删除数组元素,前者删除前后,后者删除指定元素,使用后者**@param$collect*@param$where*@param$newdata|array*@paramstring$type操作类型upd修改unset删除指定元素arr修改数组元素pull删除数组元素*@parambool$upsert是否创建*@paramint$return|1:返回bool,2:返回影响行数*@returnbool*/publicfunctionUpdMix($collect,$where,$newdata,$type='upd',$upsert=false,$return=1){if(!$this->collected||!is_array($newdata))returnfalse;$wheres=$this->GetWhere($where);if(!$wheres){$this->ErrLog('whereiserror');returnfalse;}$newdata=$this->ConvertEncode($newdata);$type=strtolower(trim($type));$types=array('upd'=>'$set','unset'=>'$unset','arr'=>'$addToSet','pull'=>'$pull');if(isset($types[$type])){$option=array();if($type=='upd')$option=array('multiple'=>true);if(in_array($type,array('upd','arr'))&&$upsert)$option['upsert']=true;$newdata=array($types[$type]=>$newdata);}else{returnfalse;}try{$result=$this->GetMonCollection($collect)->update($wheres,$newdata,$option);$result=$return==1?($result['err']?false:true):$result['n'];}catch(MongoConnectionException$e){$this->ErrLog($e->getMessage());returnfalse;}return$result;}#todoEXPLAIN函数/***对集合执行命令*@param$data*@returnbool*/publicfunctionRunCommand($data){if(is_array($data)&&$data&&$this->collected){$result=$this->db->command($data);if(isset($result['values']))return$result['values'];else$this->ErrLog("commanderror,info:".$result['errmsg'].",bad_cmd:".json_encode($result['badcmd']));}returnfalse;}/***todo聚合**/publicfunctionGroup(){}publicfunctionCount($collect,$where=array()){if(!$this->collected)returnfalse;$wheres=$this->GetWhere($where);if($where&&!$wheres)returnfalse;return$this->GetMonCollection($collect)->count($wheres);}/***返回指定键的唯一值列表*@param$collect*@param$key*@paramarray$where额外查询条件*@returnbool*/publicfunctionDistinct($collect,$key,$where=array()){if(!$this->collected)returnfalse;$wheres=$this->GetWhere($where);if($where&&!$wheres)returnfalse;try{$result=$this->GetMonCollection($collect)->distinct($key,$wheres);}catch(MongoException$e){$this->ErrLog($e->getMessage());returnfalse;}return$result;}/***删除集合中的记录*@param$collect*@param$where*@paramint$return1:返回bool,2:返回影响行数*@returnbool*/publicfunctionRemoveColl($collect,$where,$return=1){if(!$this->collected)returnfalse;$wheres=$this->GetWhere($where);if(!$wheres){$this->ErrLog('whereiserror');returnfalse;}try{$result=$this->GetMonCollection($collect)->remove($wheres);$result=$return==1?($result['err']?false:true):$result['n'];}catch(MongoConnectionException$e){$this->ErrLog($e->getMessage());returnfalse;}return$result;}/***mongo错误日志函数**@param$msg*@paramint$lever**/privatefunctionErrLog($msg,$lever=2){global$__CFG;$trace=debug_backtrace();$error_log='';$date=date("Ymd",time());$line=isset($trace[$lever]['line'])?trim($trace[$lever]['line']):'';$file=isset($trace[$lever]['file'])?trim($trace[$lever]['file']):'';$object=isset($trace[$lever]['object'])?get_class($trace[$lever]['object']):'';$args=isset($trace[$lever]['args'])?json_encode($trace[$lever]['args']):'';$error_log.="line{$line}".($object?'of'.$object:'')."(in{$file})\n";$error_log.=$args?"args:{$args}\n":'';$error_log.="msg:{$msg}";if(isset($__CFG['com']['id'])&&$__CFG['com']['id']){$com_id=$__CFG['com']['id'];}else{$com_id='common';}$log_dir=$this->config['logpath']?$this->config['logpath']:__ROOT__."data/nginx_error_log/{$com_id}/{$date}/mongo.nginx_error_log";error_log("Date:".date("Y-m-dH:i:s",$date)."\nstamp:{$date}\ntrace:{$error_log}\n\n",3,$log_dir);if(isset($__CFG['currUser'])&&$__CFG['currUser']=='root'&&isset($__CFG['daemon']['user'])){$paths=explode("nginx_error_log/",$log_dir);$pathc=explode("/",$paths[1]);$pathd=$paths[0]."nginx_error_log";foreach($pathcas$v){$pathd.="/".$v;chgrp($pathd,$__CFG['daemon']['user']);chown($pathd,$__CFG['daemon']['user']);}}}}


附件:http://down.51cto.com/data/2364629