?php
/**
* Mongodb 基本操作API,支持基本類似關(guān)系統(tǒng)型數(shù)據(jù)庫(kù)的操作接口
*
* @version 1.0
* [說(shuō)明]
*
* 1:該版本API實(shí)現(xiàn)了 Mongodb 中最基本的插入/修改/查詢/刪除操作的封裝
* 2:其它更高級(jí)的操作可通過(guò) $this->getMongo() 得到原生的對(duì)象,更多API請(qǐng)自行查閱 Mongo PHP手冊(cè),后續(xù)版本將會(huì)對(duì)增加更多的原生API封裝
* 3:該類所有API接口中的 $query 查詢參數(shù)的使用請(qǐng)以下有關(guān) [查詢條件說(shuō)明文檔]
* 4: 如果要存儲(chǔ)中文字符,則一定要使用 utf8 的編碼.
* 5:有了本類接口基本可以按關(guān)系型數(shù)據(jù)庫(kù)的概念完成Mongodb的大部分開(kāi)發(fā)操作。
*
* [查詢條件說(shuō)明文檔]
*
* 參數(shù):array('id'=>1)
* 等同:where id=1
*
* 參數(shù):array('id'=>1,'num'=>10)
* 等同:where id=1 and num=10
*
* 參數(shù):array('id'=>array($mongo->cmd('>')=>5))
* 等同:where id>5
*
* 參數(shù):array('id'=>array($mongo->cmd('!=')=>5))
* 等同:where id!=5
*
* 參數(shù):array('id'=>array($mongo->cmd('>')=>5, $mongo->cmd('')=>10))
* 等同:where id>5 and id10
*
* 參數(shù):array('id'=>array($mongo->cmd('in')=>array(2,5,6)))
* 等同:where id in (2,5,6)
*
* 參數(shù):array('id'=>array($mongo->cmd('%')=>array(2,1)))
* 等同:where id % 2 = 1
*
* 參數(shù):array($mongo->cmd('or') => array( array('id'=>array($mongo->cmd('>')=>5)), array('id'=>array($mongo->cmd('')=>10)) ) )
* 等同:where id>5 or id10
*
* 參數(shù):array('username' => new mongoRegex("/yhp.*/"))
* 等同 where username like "%yhp%"
**/
class Library_Mongodb {
/**
* Mongodb 對(duì)象句柄
*
* @var object Mongo
*/
private $_mongo = null;
/**
* 當(dāng)前選擇的數(shù)據(jù)庫(kù)
*
* @var object MongoDB
*/
private $_db = null;
/**
* 修改器命令前綴
*
* @var string
*/
private $_cmd = '$';
/**
* 調(diào)試模式 TRUE 打開(kāi) FALSE 關(guān)閉
* @var boolean
*/
const DEBUG = TRUE;
/**
* 查詢條件映射關(guān)系
*
* @var array
*/
private $_condMap = array(
'' => 'lt', // id > 1
'=' => 'lte', // id = 10
'>' => 'gt', // id > 5
'>=' => 'gte', // id >= 4
'!=' => 'ne', // id != 4
'%' => 'mod', // id % 4 = 0
'in' => 'in', // id in (1,2,3,4)
'notin' => 'nin',// id not in (1,2,3,4)
'or' => 'or', // id=1 or id=2
'not' => 'not', // !(id=1)
);
/**
* 構(gòu)造函數(shù)
*
* @param array $config 服務(wù)器配置,默認(rèn)為:
* array(
* 'host'=>'localhost', // 主機(jī)名或IP地址
* 'port'=>27017, // 端口
* 'cmd'=>'$', // 修改器命令前綴
* )
*/
public function __construct($config = array('host' => 'xxx', 'port' => 27017, 'username' => 'xxx', 'password' => 'xxx', 'db' => 'xxx', 'cmd' => '$')){
$server = sprintf("mongodb://%s:%s@%s:%s/%s", $config['username'], $config['password'], $config['host'], $config['port'], $config['db']);
// echo "connect\n";
try {
$this->_mongo = new MongoClient($server, array('connect'=>true));// 立即連接
}catch (MongoConnectionException $e){
if(self::DEBUG) {
echo $e->getMessage();
}
return false;
}
$this->selectDB($config['db']);
// 命令前綴
if(!isset($config['cmd'])){
$this->_cmd = ini_get('mongo.cmd');
if($this->_cmd == ''){
$this->_cmd = '$';
}
}
}
/* ==================================== 基本操作接口API ================================= */
/**
* 向集合(表)中插入新文檔
*
* 說(shuō)明:
* 1:類似mysql中的: insert into $colName set id=1,name='name1';
*
* @param string $colName 集合名
* @param array $sets 數(shù)據(jù),如: array('id'=>1,'name'=>'name1')
* @param boolean $safe 是否安全操作 false:不等待服務(wù)器的響應(yīng)直接返回 true:等待服務(wù)器的響應(yīng)(數(shù)據(jù)非常重要時(shí)推薦)
* @param boolean $fsync 操作后是否立即更新到碰盤(pán),默認(rèn)情況下由服務(wù)器決定
*
* @return boolean
*/
public function insert($colName, $sets, $safe=false, $fsync=false){
$col = $this->_getCol($colName);
try {
$col->insert($sets,array('w'=>$safe,'fsync'=>$fsync));
return true;
}catch (MongoCursorException $e){
return false;
}
}
/**
* 保存文檔
*
* 說(shuō)明:
* 1:如果 $sets 中有字段 "_id" 的話,則更新對(duì)應(yīng)的文檔;否則插入新文檔
*
* @param string $colName 集合名
* @param array $sets 數(shù)據(jù),如: array('id'=>1,'name'=>'name1')
* @param boolean $safe 是否安全操作 false:不等待服務(wù)器的響應(yīng)直接返回 true:等待服務(wù)器的響應(yīng)(數(shù)據(jù)非常重要時(shí)推薦)
* @param boolean $fsync 操作后是否立即更新到碰盤(pán),默認(rèn)情況下由服務(wù)器決定
*
* @return boolean
*/
public function save($colName, $sets, $safe=false, $fsync=false){
// 處理 '_id' 字段
$sets = $this->_parseId($sets);
$ret = $this->_getCol($colName)->save($sets,array('w'=>$safe,'fsync'=>$fsync));
return $ret;
}
/**
* 刪除集合中的文檔記錄
*
* 說(shuō)明:
* 1:類似mysql中的: delete from $colName where id=1;
*
* @param string $colName 集合名
* @param array $query 查詢條件,如果為空數(shù)組的話,則會(huì)刪除所有記錄.具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param boolean $delAll 是否刪除所以條例查詢的記錄,默認(rèn)為 true,當(dāng)為 false是,類似效果 delete from tab where id=1 limit 1;
* @param boolean $safe 是否安全操作 false:不等待服務(wù)器的響應(yīng)直接返回 true:等待服務(wù)器的響應(yīng)(數(shù)據(jù)非常重要時(shí)推薦)
* @param boolean $fsync 操作后是否立即更新到碰盤(pán),默認(rèn)情況下由服務(wù)器決定
*
* @return boolean
*/
public function delete($colName,$query=array(),$delAll=true,$safe=false,$fsync=false){
// 自動(dòng)處理 '_id' 字段
$query = $this->_parseId($query);
// 刪除選項(xiàng)
$options = array(
'justOne' => !$delAll,
'w' => $safe,
'fsync' => $fsync,
);
$col = $this->_getCol($colName);
return $col->remove($query,$options);
}
/**
* 刪除整個(gè)集合
*
* 說(shuō)明:
* 1:集合中的索引也會(huì)被刪除
*
* @param string $colName 集合名
*
* @return array
*/
public function dropCol($colName){
return $this->_getCol($colName)->drop();
}
/**
* 更新集合文檔記錄
*
* 說(shuō)明:
* 1:類似mysql中的: update $colName set name='mongo' where id=10;
*
* @param string $colName 集合名
* @param array $newDoc 要更新的文檔記錄
* @param array $query 查詢條件,如果為空數(shù)組則更新所有記錄.具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param string $option 操作選項(xiàng),可選擇項(xiàng)如下;
*
* 'set':只修改指定的字段(默認(rèn)值,如果這個(gè)鍵不存在,則創(chuàng)建它。存在則更新).
* 示例: update('user', array('name'=>'mongo'), array('id'=>10));
* 類似: update user set name='mongo' where id=10;
*
* 'inc':將指定的字段累加/減(如果值為負(fù)數(shù)則是相減,不存在鍵則創(chuàng)建。字段類型一定要是數(shù)字)
* 示例:update('user', array('num'=>1), array('id'=>10), 'inc');
* 類似: update user set num=num+1 where id=10;
*
* 'push':將文檔添加到指定鍵中(數(shù)組),如果鍵不存在則會(huì)自動(dòng)創(chuàng)建,存在則添加到該鍵的尾端。
* 示例:update('user', array('comm'=>array('commid'=>1,'title'=>'title1')), array('id'=>1), 'push');
* 解說(shuō):為 id=1 的記錄添加一個(gè) comm 的評(píng)論字段,該字段對(duì)應(yīng)一個(gè) array('commid'=>1,'title'=>'title1') 的新文檔。
*
* 'pop':將指定鍵中的文檔刪除(數(shù)組)
* 示例:update('user', array('comm'=>array('commid'=>1)), array('id'=>1), 'pop');
* 解說(shuō):刪除 id=1 的記錄中 comm 對(duì)應(yīng)的文檔集合中 'commid'=>1 對(duì)應(yīng)的文檔.
*
* 'unset':在文檔中刪除指定的鍵
* 示例:update('user', array('name'=>1), array('id'=>1), 'unset');
* 解說(shuō): 將 user 集合中將 id=1 對(duì)應(yīng)的文檔中的 name 字段刪除
*
* 'pull':刪除文檔中匹配其值的鍵
* 示例:update('user', array('name'=>'youname'), array('id'=>1), 'pull');
* 解說(shuō):將 user 集合中將 id=1 對(duì)應(yīng)的文檔中的 name='youname' 的字段刪除
*
* 'addToSet':如果值不存在就添加(避免重復(fù)添加)
* 示例:update('user', array('names'=>'youname'), array('id'=>1), 'addToSet');
* 解說(shuō):向 user 集合中 id=1 對(duì)應(yīng)的文檔中的 names 字段添加 'youname' 這個(gè)值(不存在時(shí)才添加)
*
* 'replace':用 $newDoc 新文檔替換 $query 所找到的文檔
* 示例:update('user', array('newid'=>1,'newnames'=>'name1'), array('id'=>1), 'replace');
* 解說(shuō):將 user 集合中 id=1 對(duì)應(yīng)的文檔用 array('newid'=>1,'newnames'=>'name1') 的新文檔替換
*
* @param boolean $upAll 是否更新找到的所有記錄
* @param boolean $upsert 如果查詢條件不存在時(shí),是否以查詢條件和要更新的字段一起新建一個(gè)集合
* @param boolean $safe 是否安全刪除 false:不等待服務(wù)器的響應(yīng)直接返回 true:等待服務(wù)器的響應(yīng)(數(shù)據(jù)非常重要時(shí)推薦)
* @param boolean $fsync 操作后是否立即更新到碰盤(pán),默認(rèn)情況下由服務(wù)器決定
*
* @return boolean
*/
public function update($colName,$newDoc,$query=array(),$option='set',$upAll=true,$upsert=false,$safe=false,$fsync=false){
// 自動(dòng)處理 '_id' 字段
$query = $this->_parseId($query);
// 得到集合
$col = $this->_getCol($colName);
// 重新組合新文檔
if($option != 'replace'){
$newDoc = array($this->cmd($option) => $newDoc);
}
// 更新條件
$options = array(
'upsert' => $upsert,
'multiple' => $upAll,
'w' => $safe,
'fsync' => $fsync,
);
return $col->update($query,$newDoc,$options);
}
/**
* 查詢文檔集,返回二維數(shù)組
*
* 說(shuō)明:
* 1:類似mysql中的 select * from table
*
* 示例:select('user');
* 類似:select * from user;
*
* 示例:select('user',array('id','name'));
* 類似:select id,name from user;
*
* 示例:select('user',array('id','name'),array('id'=>1));
* 類似:select id,name from user where id=1;
*
* 示例:select('user',array('id','name'),array('id'=>1),array('num'=>1));
* 類似:select id,name from user where id=1 order by num asc;
*
* 示例:select('user',array('id','name'),array('id'=>1),array('num'=>1),10);
* 類似:select id,name from user where id=1 order by num asc limit 10;
*
* 示例:select('user',array('id','name'),array('id'=>1),array('num'=>1),10,2);
* 類似:select id,name from user where id=1 order by num asc limit 2,10;
*
*
*
* @param string $colName 集合名
* @param array $query 查詢條件,具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param array $fields 結(jié)果集返回的字段, array():表示返回所有字段 array('id','name'):表示只返回字段 "id,name"
* @param array $sort 排序字段, array('id'=>1):表示按id字段升序 array('id'=>-1):表示按id字段降序 array('id'=>1, 'age'=>-1):表示按id升序后再按age降序
* @param int $limit 取多少條記錄
* @param int $skip 跳過(guò)多少條(從多少條開(kāi)始)
*
* @return array
*/
public function select($colName,$query=array(),$fields=array(),$sort=array(),$limit=0,$skip=0){
// 得到集合
$col = $this->_getCol($colName);
// 自動(dòng)處理 '_id' 字段
$query = $this->_parseId($query);
// 結(jié)果集偏歷
$cursor = $col->find($query,$fields);
// 排序
if($sort){
$cursor->sort($sort);
}
// 跳過(guò)記錄數(shù)
if($skip > 0){
$cursor->skip($skip);
}
// 取多少行記錄
if($limit > 0){
$cursor->limit($limit);
}
$result = array();
foreach($cursor as $row){
$result[] = $this->_parseArr($row);
}
return $result;
}
/**
* 統(tǒng)計(jì)文檔記錄數(shù)
*
* @param string $colName 集合名
* @param array $query 查詢條件,具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param int $limit 取多少條記錄
* @param int $skip 跳過(guò)多少條
* @return unknown
*/
public function count($colName,$query=array(),$limit=0,$skip=0){
return $this->_getCol($colName)->count($query,$limit,$skip);
}
/**
* 返回集合中的一條記錄(一維數(shù)組)
*
* @param string $colName 集合名
* @param array $query 查詢條件,具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param array $fields 結(jié)果集返回的字段, array():表示返回所有字段 array('id','name'):表示只返回字段 "id,name"
*
* @return array
*/
public function fetchRow($colName,$query=array(), $fields=array()){
// 得到集合名
$col = $this->_getCol($colName);
// 自動(dòng)處理 '_id' 字段
$query = $this->_parseId($query);
// 處理結(jié)果集
return $this->_parseArr($col->findOne($query,$fields));
}
/**
* 返回符合條件的文檔中字段的值
*
* @param string $colName 集合名
* @param array $query 查詢條件,具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param string $fields 要取其值的字段,默認(rèn)為 "_id" 字段,類似mysql中的自增主鍵
*
* @return mixed
*/
public function fetchOne($colName,$query=array(), $fields='_id'){
$ret = $this->fetchRow($colName,$query,array($fields));
return isset($ret[$fields]) ? $ret[$fields] : false;
}
/**
* 返回查詢文檔集合集中指定字段的值(一維數(shù)組)
*
* @param string $colName 集合名
* @param array $query 查詢條件,具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param string $fields 要取其值的字段,默認(rèn)為 "_id" 字段,類似mysql中的自增主鍵
*
* @return array
*/
public function fetchCol($colName,$query=array(), $fields='_id'){
$result = array();
$list = $this->select($colName,$query,array($fields));
foreach ($list as $row){
$result[] = $row[$fields];
}
return $result;
}
/**
* 返回指定下標(biāo)的查詢文檔集合(二維數(shù)組)
*
* @param string $colName 集合名
* @param array $query 查詢條件,具體請(qǐng)看 [查詢條件說(shuō)明文檔]
* @param string $fields 要取其值的字段,默認(rèn)為 "_id" 字段,類似mysql中的自增主鍵
*
* @return array
*/
public function fetchAssoc($colName,$query=array(), $fields='_id'){
$result = array();
$list = $this->select($colName,$query);
foreach ($list as $row){
$key = $row[$fields];
$result[][$key] = $row;
}
return $result;
}
/* ==================================== 輔助操作接口API ================================= */
/**
* 返回命令或命令前綴
*
* @param string $option 命令,如果為空時(shí)則返回命令前綴
*
* @return string
*/
public function cmd($option=''){
// 只返回命令前綴
if($option == ''){
return $this->_cmd;
}
// 如果是操作符
if(isset($this->_condMap[$option])){
$option = $this->_condMap[$option];
}
return $this->_cmd.$option;
}
/**
* 選擇或創(chuàng)建數(shù)據(jù)庫(kù)(注意:新創(chuàng)建的數(shù)據(jù)庫(kù)如果在關(guān)閉連接前沒(méi)有寫(xiě)入數(shù)據(jù)將會(huì)被自動(dòng)刪除)
*
* @param string $dbname 數(shù)據(jù)庫(kù)名
*/
public function selectDB($dbname){
$this->_db = $this->_mongo->selectDB($dbname);
}
/**
* 得到所有的數(shù)據(jù)庫(kù)
*
* @param boolean $onlyName 是否只返回?cái)?shù)據(jù)庫(kù)名的數(shù)組
* @return array
*/
public function allDB($onlyName=false){
$ary = $this->_mongo->listDBs();
if($onlyName){
$ret = array();
foreach ($ary['databases'] as $row){
$ret[] = $row['name'];
}
return $ret;
}else{
return $ary;
}
}
/**
* 刪除數(shù)據(jù)庫(kù)
*
* @return array
*/
public function dropDB($dbname){
return $this->_mongo->dropDB($dbname);
}
/**
* 關(guān)閉連接
*
*/
public function close(){
$this->_mongo->close();
}
/**
* 得到 Mongo 原生對(duì)象,進(jìn)行其它更高級(jí)的操作,詳細(xì)請(qǐng)看PHP手冊(cè)
*
*/
public function getMongo(){
return $this->_mongo;
}
/**
* 返回最后的錯(cuò)誤信息
*
* @return array
*/
public function getError(){
return $this->_db->lastError();
}
/* ======================= 以下為私有方法 ====================== */
// 解析數(shù)據(jù)組中的'_id'字段(如果有的話)
private function _parseId($arr){
if(isset($arr['_id'])){
$arr['_id'] = new MongoId($arr['_id']);
}
return $arr;
}
// 得到集合對(duì)象
private function _getCol($colName){
return $this->_db->selectCollection($colName);
}
// 解析數(shù)組中的"_id"并且返回
private function _parseArr($arr){
if(!empty($arr)) {
$ret = (array)$arr['_id'];
$arr['_id'] = $ret['$id'];
}
return $arr;
}
}//End Class
?>
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《PHP+MongoDB數(shù)據(jù)庫(kù)操作技巧大全》、《PHP基于pdo操作數(shù)據(jù)庫(kù)技巧總結(jié)》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門(mén)教程》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門(mén)教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》