天天看點

MongoDB實戰(4)MapReduce

在 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: &lt;collection&gt;,</code>

<code>    </code><code>map: &lt;</code><code>function</code><code>&gt;,</code>

<code>    </code><code>reduce: &lt;</code><code>function</code><code>&gt;,</code>

<code>    </code><code>out: &lt;output&gt;,</code>

<code>    </code><code>query: &lt;document&gt;,</code>

<code>    </code><code>sort</code><code>: &lt;document&gt;,</code>

<code>    </code><code>limit: &lt;number&gt;,</code>

<code>    </code><code>finalize: &lt;</code><code>function</code><code>&gt;,</code>

<code>    </code><code>scope: &lt;document&gt;,</code>

<code>    </code><code>jsMode: &lt;boolean&gt;,</code>

<code>    </code><code>verbose: &lt;boolean&gt;</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&gt;10 的資料,然後再進行統計,是以就沒有 age=9 的數

據了。

本文轉自shayang8851CTO部落格,原文連結:http://blog.51cto.com/janephp/1323812,如需轉載請自行聯系原作者

繼續閱讀