mongodb的mapreduce用法及php範例程式碼

來源:互聯網
上載者:User
MongoDB雖然不像我們常用的mysql,sqlserver,oracle等關係型資料庫有group by函數那樣方便分組,但是MongoDB要實現分組也有3個辦法:

* Mongodb三種分組方式:

* 1、group(先篩選再分組,不支援分區,對資料量有所限制,效率不高)

* 2、mapreduce(基於js引擎,單線程執行,效率較低,適合用做後台統計等)

* 3、aggregate(推薦) (如果你的PHP的mongodb驅動版本需>=1.3.0,推薦你使用aggregate,效能要高很多,並且使用上要簡單些,不過1.3的目前還不支援賬戶認證模式,可以通過 http://pecl.php.net/package/mongo 查看更新日誌和Bug)

下面就來看下mapreduce方式:

Mongodb官網對MapReduce介紹:

Map/reduce in MongoDB is useful for batch processing of data and aggregation operations. It is similar in spirit to using something like Hadoop with all input coming from a collection and output going to a collection. Often, in a situation where you would have used GROUP BY in SQL, map/reduce is the right tool in MongoDB.

大致意思是: Mongodb中的Map/reduce主要是用來對資料進行批量處理和彙總操作,有點類似於使用Hadoop對集合資料進行處理,所有輸入資料都是從集合中擷取,而MapReduce後輸出的資料也都會寫入到集合中。通常類似於我們在SQL中使用Group By語句一樣。

使用MapReduce要實現兩個函數:Map和Reduce。Map函數調用emit(key,value)遍曆集合中所有的記錄,將key與value傳給Reduce函數進行處理。Map函數和Reduce函數是使用Javascript編寫的,並可以通過db.runCommand或mapreduce命令來執行MapReduce操作。

MapReduce命令如下:

db.runCommand({ mapreduce : <collection>, map : <mapfunction>, reduce : <reducefunction> [, query : <queryfilterobject>] [, sort : <sortthequery.usefulforoptimization>] [, limit : <numberofobjectstoreturnfromcollection>] [, out : <output-collectionname>] [, keeptemp: <true|false>] [, finalize : <finalizefunction>] [, scope : <objectwherefieldsgointojavascriptglobalscope >] [, verbose : true] });

參數說明:

mapreduce:要操作的目的地組合

map:映射函數(產生鍵值對序列,作為Reduce函數的參數)

reduce:統計函數

query:目標記錄過濾

sort:對目標記錄排序

limit:限制目標記錄數量

out:統計結果存放集合(如果不指定則使用臨時集合,在用戶端斷開後自動刪除)

keeptemp:是否保留臨時集合

finalize:最終處理函數(對reduce返回結果執行最終整理後存入結果集合)

scope:向map、reduce、finalize匯入外部變數

verbose:顯示詳細的時間統計資訊


map函數
map函數調用當前對象,並處裡對象的屬性,傳值給reduce,map方法使用this來操作當前對象,最少調用一次emit(key,value)方法來向reduce提供參數,其中emit的key為最終資料的id。

reduce函數
接收一個值和數組,根據需要對數組進行合并分組等處理,reduce的key就是emit(key,value)的key,value_array是同個key對應的多個value數組。

Finalize函數
此函數為可選函數,可在執行完map和reduce後執行,對最後的資料進行統一處理。

看完基本介紹,我們再來看一個執行個體:

已知集合feed,測試資料如下:

{ "_id": ObjectId("50ccb3f91e937e2927000004"), "feed_type": 1, "to_user": 234, "time_line": "2012-12-16 01:26:00"}{ "_id": ObjectId("50ccb3ef1e937e0727000004"), "feed_type": 8, "to_user": 123, "time_line": "2012-12-16 01:26:00"}{ "_id": ObjectId("50ccb3e31e937e0a27000003"), "feed_type": 1, "to_user": 123, "time_line": "2012-12-16 01:26:00"}{ "_id": ObjectId("50ccb3d31e937e0927000001"), "feed_type": 1, "to_user": 123, "time_line": "2012-12-16 01:26:00"}
我們按動態類型feed_type和使用者to_user進行分組統計,實現結果:

feed_type to_user cout
1 234 1
8 123 1
1 123 2







實現代碼:

//編寫map函數$map = ' function() { var key = {to_user:this.to_user,feed_type:this.feed_type}; var value = {count:1}; emit(key,value); } '; //reduce 函數$reduce = ' function(key, values) { var ret = {count:0}; for(var i in values) { ret.count += 1; } return ret; }';//查詢條件$query = null; //本執行個體中沒有查詢條件,設定為null$mongo = new Mongo('mongodb://root:root@127.0.0.1: 28017/'); //連結mongodb,帳號和密碼為root,root$instance = $mongo->selectDB("testdb");//執行此命令後,會建立feed_temp_res的臨時集合,並將統計後的資料放在該集合中$cmd = $instance->command(array('mapreduce' => 'feed','map' => $map,'reduce' => $reduce,'query'=> $query,'out' => 'feed_temp_res'));//查詢臨時集合中的統計資料,驗證統計結果是否和預期結果一致$cursor = $instance->selectCollection('feed_temp_res')->find();$result = array();try {while ($cursor->hasNext()){$result[] = $cursor->getNext();}}catch (MongoConnectionException $e){echo$e->getMessage();}catch (MongoCursorTimeoutException $e){echo$e->getMessage();}catch(Exception$e){echo$e->getMessage();}//testvar_dump($result);
下面是輸出的結果,和預期結果一致

{ "_id": { "to_user": 234, "feed_type": 1 }, "value": { "count": 1 }}{ "_id": { "to_user": 123, "feed_type": 8 }, "value": { "count": 1 }}{ "_id": { "to_user": 123, "feed_type": 1 }, "value": { "count": 2 }}

以上只是簡單的統計實現,你可以實現複雜的條件統計編寫複雜的reduce函數,可以增加查詢條件,排序等等。

附上mapReduce資料庫處理函數(簡單封裝)

/** * mapReduce分組 * * @param string $table_name 表名(要操作的目的地組合名) * @param string $map 映射函數(產生鍵值對序列,作為 reduce 函數參數) * @param string $reduce 統計處理函數 * @param array $query 過濾條件 如:array('uid'=>123) * @param array $sort 排序 * @param number $limit 限制的目標記錄數 * @param string $out 統計結果存放集合 (不指定則使用tmp_mr_res_$table_name, 1.8以上版本需指定) * @param bool $keeptemp 是否保留臨時集合 * @param string $finalize 最終處理函數 (對reduce返回結果進行最終整理後存入結果集合) * @param string $scope 向 map、reduce、finalize 匯入外部js變數 * @param bool $jsMode 是否減少執行過程中BSON和JS的轉換,預設true(註:false時 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可處理非常大的mapreduce,//true時BSON-->js-->map-->reduce-->BSON) * @param bool $verbose 是否產生更加詳細的伺服器日誌 * @param bool $returnresult 是否返回新的結果集 * @param array &$cmdresult 返回mp命令執行結果 array("errmsg"=>"","code"=>13606,"ok"=>0) ok=1表示執行命令成功 * @return*/ function mapReduce($table_name,$map,$reduce,$query=null,$sort=null,$limit=0,$out='',$keeptemp=true,$finalize=null,$scope=null,$jsMode=true,$verbose=true,$returnresult=true,&$cmdresult){ if(empty($table_name) || empty($map) || empty($reduce)){ return null; } $map = new MongoCode($map); $reduce = new MongoCode($reduce); if(empty($out)){ $out = 'tmp_mr_res_'.$table_name; } $cmd = array( 'mapreduce' => $table_name, 'map' => $map, 'reduce' => $reduce, 'out'=>$out ); if(!empty($query) && is_array($query)){ array_push($cmd, array('query'=>$query)); } if(!empty($sort) && is_array($sort)){ array_push($cmd, array('sort'=>$query)); } if(!empty($limit) && is_int($limit) && $limit>0){ array_push($cmd, array('limit'=>$limit)); } if(!empty($keeptemp) && is_bool($keeptemp)){ array_push($cmd, array('keeptemp'=>$keeptemp)); } if(!empty($finalize)){ $finalize = new Mongocode($finalize); array_push($cmd, array('finalize'=>$finalize)); } if(!empty($scope)){ array_push($cmd, array('scope'=>$scope)); } if(!empty($jsMode) && is_bool($jsMode)){ array_push($cmd, array('jsMode'=>$jsMode)); } if(!empty($verbose) && is_bool($verbose)){ array_push($cmd, array('verbose'=>$verbose)); } $dbname = $this->curr_db_name; $cmdresult = $this->mongo->$dbname->command($cmd); if($returnresult){ if($cmdresult && $cmdresult['ok']==1){ $result = $this->find($out, array()); } } if($keeptemp==false){ //刪除集合 $this->mongo->$dbname->dropCollection($out); } return$result; }

MongoDB官方網站介紹:

MapReduce介紹 http://docs.mongodb.org/manual/core/map-reduce/

Aggregation介紹 http://docs.mongodb.org/manual/aggregation/

以上就介紹了mongodb的mapreduce用法及php範例程式碼,包括了方面的內容,希望對PHP教程有興趣的朋友有所協助。

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.