來講說MongoDB中的數據聚合工具。javascript
Aggregate是MongoDB提供的衆多工具中的比較重要的一個,相似於SQL語句中的GROUP BY
。聚合工具可讓開發人員直接使用MongoDB原生的命令操做數據庫中的數據,而且按照要求進行聚合。聚合不只極大提高了開發的效率,更重要的是,原生的工具運行效率比本身寫聚合的方法高到不知道哪裏去了。
下面簡單說一下PHP開發環境下如何使用MongoDB的數據聚合工具 Aggregation Pipleline和Group。其實PHP下的MongoDB使用和原生差很少,無非是語法從JavaScript變成了PHP而已,大體的操做流程是差很少,命令的格式也是很是相像的。基本上只要會看MongoDB的文檔,就能經過PHP操做MongoDB了。php
關於Aggregation,官方文檔在這裏。我這裏就半翻譯半扯淡(固然大部分是扯淡)說一下Aggregation Pipleline。java
管道在*nix中將上一個命令輸出的數據做爲下一個命令的參數。MongoDB中的管道操做是能夠重複的,基於這個概念,MongoDB中的管道聚合能夠有很是實用的玩法,好比對聚合的結果進行排序。mongodb
借用一下官方的圖,這裏aggregate的命令爲:數據庫
[ {$match: {status: "A"}}, {$group: {_id: "$cust_id", total: {$sum: "$amount"}}} ]
aggreagte是一個數組,其中包含多個對象(命令),經過遍歷Pipleline數組對collection中的數據進行操做。
解釋一下例子中的配置項意思。數組
$match
:查詢條件函數
$match
是配置查詢數據時的條件。這裏的語法和查詢數據庫的時候一毛同樣,也就再也不贅述了,看一下MongoDB的CRUD文檔便可。$group
:聚合的配置工具
_id
表明你想聚合的數據的主鍵,例如上述數據中,你想聚合全部cust_id
相同的條目的amount
的總和,那_id
即被設置爲cust_id
。_id
爲必須,可是你能夠填寫一個空值。total
表明你最後想輸出的數據之一,這裏total
是每條結果中amount
的總和。$sum
是一個聚合的操做符,另外的操做符你能夠在官方文檔中找到。上圖中的命令表示對相同主鍵(_id)下的amount
進行求和。若是你想要計算主鍵出現的次數,能夠把命令寫成以下的形式{$sum: 1}
看一下圖例,全部的數據先通過$match
命令,只留下了status
爲A的數據,接着,對篩選出的數據進行聚合操做,對相同cust_id的數據進行計算amount
總和的操做,最後輸出結果。性能
這裏說一下$sort
操做符。前面說過,利用管道的特性,能夠作到對結果進行排序。因此只須要在$group
操做以後使用$sort
操做便可,這點在報表的製做上十分實用。何況使用MongoDB對結果進行排序也能夠儘可能優化性能。
MongoDB另外一個重要的聚合工具就是Group,所不一樣的是,Aggregate操做中,傳入的Pipleline是一個包含多個對象的數組,每個對象表明了一個命令。而Group有傳入的命令中共有六個參數,其中三個……是JavaScript函數,所以每次查詢到匹配的數據,都會被轉換爲對象傳入函數。從運行效率上來講,Group確定比Aggregate差一大截。可是Group的優點在於靈活,由於配置項能夠經過本身編寫函數來實現。可是須要注意的是,儘管這樣作看起來很是靈活方便,可是一旦函數複雜度過大,將大大影響Group的性能,所以箇中取捨還須要本身定奪。
從我我的來講,用得最多的是key
、cond
、$reduce
、inital
這四個命令。
使用上面Aggregation Pipleline中的數據爲例。
key
:其實和上邊說的Aggregation Pipleline中的_id
是同樣的。假設這裏是{cust_id: 1}cond
:和上邊說的$match
是同樣的。$reduce
:一個函數,對匹配到的數據進行操做,這個放在後面說。initial
:初始數據,假設咱們這裏是{count: 0}
。$reduce
:
function(obj, prev) { prev.count += obj.amount; }
$reduce
的函數(仍是匿名的)能夠傳入兩個參數,第一個是被轉換爲對象的條目,第二個是被實例化的initial對象。
最後的結果和Aggregate操做的同樣:
{ retval: [ { cust_id: "A123", count: 750 }, { cust_id: "B212", count: 200 } ], count: 3, keys: 2, ok: 1 }
PHP中的Mongo操做和原生的使用JavaScript操做很是像。例如第一個例子的代碼以下:
<?php $mongo = new MongoClient(DB_CONNECT); $db = $mongo->db; $collection = $db->selectCollection('orders'); $pipleline = array( array( '$match' => array( 'status' => array( '$eq' => 'A', ), ), ), array( '$group' => array( '_id' => '$cust_id', 'total' => array( '$sum' => '$amount', ), ), ), ); $a = $collection->aggregate($pipleline); $result = isset($a['result']) ? $a['result'] : array();
第二個例子的代碼以下
<?php $mongo = new MongoClient(DB_CONNECT); $db = $mongo->db; $collection = $db->selectCollection('orders'); $keys = array('cust_id' => 1); $initial = array('count' => 0); $reduce = 'function(obj, prev) {prev.count += obj.amount;}'; $cond = array('condition' => array('status' => 'A')); $g = $collection->group($keys, $initial, $reduce, $cond); $retval = isset($g['retval']) ? $g['retval'] : array();
其餘的功能,須要本身多參考PHP官方文檔和Mongo的文檔進行嘗試了。