在 MongoDB 上使用 Map/Reduce進行并行"統計"很容易。
使用 MapReduce 要實作兩個函數 Map 函數和 Reduce 函數,Map 函數調用 emit(key, value),
周遊 collection 中所有的記錄, 将key 與 value 傳遞給 Reduce 函數進行處理。
Map函數和Reduce函數可以使用 JavaScript 來實作,可以通過 db.runCommand 或 mapReduce 指令來執行一個MapReduce 的操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<code>db.runCommand(</code>
<code>{</code>
<code> </code><code>mapReduce: <collection>,</code>
<code> </code><code>map: <</code><code>function</code><code>>,</code>
<code> </code><code>reduce: <</code><code>function</code><code>>,</code>
<code> </code><code>out: <output>,</code>
<code> </code><code>query: <document>,</code>
<code> </code><code>sort</code><code>: <document>,</code>
<code> </code><code>limit: <number>,</code>
<code> </code><code>finalize: <</code><code>function</code><code>>,</code>
<code> </code><code>scope: <document>,</code>
<code> </code><code>jsMode: <boolean>,</code>
<code> </code><code>verbose: <boolean></code>
<code>})</code>
參數說明:
mapreduce: 要操作的目标集合。
map: 映射函數 (生成鍵值對序列,作為 reduce 函數參數)。
reduce: 統計函數。
out: 統計結果存放集合 (不指定則使用臨時集合,在用戶端斷開後自動删除)。
query: 目标記錄過濾
sort: 目标記錄排序。
limit: 限制目标記錄數量。
finalize: 最終處理函數 (對 reduce 傳回結果進行最終整理後存入結果集合)
scope: 向 map、reduce、finalize 導入外部變量。
jsMode: 是否轉換Bson格式在map和reduce執行間
verbose: 顯示詳細的時間統計資訊。
下面我們來搞一個例子吧:
準備一些資料:
<a href="http://blog.51cto.com/attachment/201311/135332174.png" target="_blank"></a>
接下來我們示範如何統計各個班的學生數量
Map:
Map 函數必須調用 emit(key, value) 傳回鍵值對,使用 this 通路目前待處理的 Document。
<code>m = </code><code>function</code><code>(){</code>
<code> </code><code>emit(this.classid,1);</code>
<code>}</code>
value 可以使用 JSON Object 傳遞 (支援多個屬性值)。
例如:emit(this.classid, {count:1})
Reduce:
Reduce 函數接收的參數類似 Group 效果,将 Map 傳回的鍵值序列組合成 { key, [value1,
value2, value3, value...] } 傳遞給 reduce。
<code>r = </code><code>function</code><code>(key,values){</code>
<code> </code><code>var x = 0;</code>
<code> </code><code>values.forEach(</code><code>function</code><code>(</code><code>v</code><code>){x += </code><code>v</code><code>});</code>
<code> </code><code>return</code> <code>x;</code>
Reduce 函數對這些 values 進行 "統計" 操作,傳回結果可以使用 JSON Object。
Result:
<a href="http://blog.51cto.com/attachment/201311/140428607.png" target="_blank"></a>
mapReduce() 将結果存儲在 "students_res" 表中。
<a href="http://blog.51cto.com/attachment/201311/140552995.png" target="_blank"></a>
Finalize:
利用 finalize() 我們可以對 reduce() 的結果做進一步處理。
<code>f = </code><code>function</code><code>(key,value){</code>
<code> </code><code>return</code> <code>{classid:key,count:value}</code>
我們再重新計算一次,看看結果:
<a href="http://blog.51cto.com/attachment/201311/141023438.png" target="_blank"></a>
Options:
我們還可以添加更多的控制細節。
<code>db.runCommand({</code>
<code> </code><code>mapreduce:</code><code>"stu"</code><code>,</code>
<code> </code><code>map:m,</code>
<code> </code><code>reduce:r,</code>
<code> </code><code>out:</code><code>"stu_res"</code><code>,</code>
<code> </code><code>finalize:f,</code>
<code> </code><code>query:{age:{$gt:10}}</code>
<code>});</code>
<a href="http://blog.51cto.com/attachment/201311/144409503.png" target="_blank"></a>
可以看到先進行了過濾,隻取 age>10 的資料,然後再進行統計,是以就沒有 age=9 的數
據了。
本文轉自shayang8851CTO部落格,原文連結:http://blog.51cto.com/janephp/1323812,如需轉載請自行聯系原作者