轉載請註明作者:wetouns
在使用MONGODB的時候寫查詢語句總是一件讓人蛋疼的事情,如果查詢複雜一點,要嵌套好多層對象,於是我就想,能不能使用類似SQL的文法來進行查詢呢,這樣子代碼看起來更加易懂,書寫也更為簡單,於是就花了些時間把這個想法變為現實該解析器會將類似SQL的文法轉換成MONGODB的查詢對象,目前條件判斷只支援and和or,以及>,<,>=,<=,=的查詢,還支援括弧表示判斷的優先順序哦,更多的暫時不支援,想擴充的可以自己改源碼,簡單說明一下文法和用法吧
例1,我要查詢a=0的文檔
$query = new MongoQueryParser();$query->query("a=0");$queryRst = $query->result;
最終$queryRst的結果將會如
例2:
這回來個複雜點的
$query = new MongoQueryParser();$query->query("a=0 && b > 2");$queryRst = $query->result;結果如下
例3:
再來個更複雜的
$query = new MongoQueryParser();$query->query("(a=0 && b > 2) || c <= 5");$queryRst = $query->result;結果如下
看完以上3個例子,相信不用說明用法,應該也會用了吧,嘿嘿,廢話少說,貼上解析器的源碼
result =[];}public $result;public $leftFirstReg = "/\\(([^\\s]+)\\)(&&|\\|\\|)([^\\s]+$)/";//匹配左括弧優先public $rightFirstReg = "/([^\\s]+?)(&&|\\|\\|)\\(([^\\s]+)\\)$/";//右括弧優先public $allReg = "/\\(([^\\s]+)\\)(&&|\\|\\|)\\(([^\\s]+)\\)$/";//左右括弧模式public $reg1 = "/([^\\s]+)(&&|\\|\\|)([^\\s]+)/";public $reg2 = "/([\\w]+)([=<>]+)([^\\s]+)/";public $opMap = [">"=>'$gt',"<"=>'$lt',">="=>'$gte',"<="=>'$lte'];private $meetOr = false;/** * 將自訂的查詢語句轉換成MONGODB的查詢語句 * 例1:a=3 * 例2:a>0&&a<2 * 例3:a>0&&a<2||c>3 */function query($query){$query =preg_replace("/\s/","",$query);$this->result = $this->exec($query,false,false);return $this->result;}function exec($query,$layer,$fromAnd){if(preg_match($this->allReg, $query,$matches1) > 0 || preg_match($this->rightFirstReg, $query,$matches2) > 0 ||preg_match($this->leftFirstReg, $query,$matches3) > 0 || preg_match($this->reg1, $query,$matches4)){$mat = null;$leftSame = false;$rightSame = false;if(count($matches1) > 0){$mat = $matches1;}else if(count($matches2) > 0){$leftSame = true;$rightSame = false;$mat = $matches2;}else if(count($matches3) > 0){$leftSame = false;$rightSame = true;$mat = $matches3;}else if(count($matches4) > 0){$leftSame = true;$rightSame = true;$mat = $matches4;}$op = $mat[2];$left = $mat[1];$right = $mat[3];if($op == "&&"){//如果操作符是AND$rst = null;if(!$layer || !$fromAnd){//如果不同層,或者調用來自上一層的or,那麼就建立一個$and操作符$rst['$and'] = [];$larr = $this->exec($mat[1],$leftSame,true);$rarr = $this->exec($mat[3],$rightSame,true);$rst['$and'] = $this->mergeArr($rst['$and'],$larr, $rarr);return $rst;}else{//如果同層,直接把值都放到同層數組去$rst = array_merge($this->exec($mat[1],$leftSame,true),$this->exec($mat[3],$rightSame,true));return $rst;}}else if($op == "||"){if(!$layer || $fromAnd){//如果不同層$rst['$or'] = [];$larr = $this->exec($mat[1],$leftSame,false);$rarr = $this->exec($mat[3],$rightSame,false);$rst['$or'] = $this->mergeArr($rst['$or'],$larr, $rarr);}else{$rst = [];$rst = array_merge($this->exec($mat[1],$leftSame,false),$this->exec($mat[3],$rightSame,false));}return $rst;}}else{//如果最終已經分解成a=b的形式時,就在此解析preg_match($this->reg2, $query,$matches);if(count($matches) >= 4){$left = $matches[1];$op = $matches[2];$right = $matches[3];$rst = [];if($op == "="){if(is_numeric($right)){$rst[$left] = (float)$right;}else{$rst[$left] = $right;}}else{if(!isset($rst[$left])){$rst[$left] = [];}if(is_numeric($right)){$rst[$left][$this->opMap[$op]] = (float)$right;}else{$rst[$left][$this->opMap[$op]] = $right;}}return $rst;}}}function mergeArr($rst,$larr,$rarr){foreach ($larr as $lk=>$lv){$lcond = [];$lcond[$lk] = $lv;$rst[] = $lcond;}foreach ($rarr as $rk=>$rv){$rcond = [];$rcond[$rk] = $rv;$rst[] = $rcond;}return $rst;}}?>
好了,就這麼多內容,我想應該會有人需要的
有什麼問題直接留言吧
以上就介紹了寫了一個PHP版本的MONGODB文法解析器,可以通過類似SQL的文法來進行查詢,不知道有人需要不,分享一下吧,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。