關於mongodb的mapReduce

來源:互聯網
上載者:User

標籤:

由於nodejs本身的限制,在程式中使用js進行大批次運算效率不高。而V8引擎自身對記憶體大小的限制(64位系統下1.4G),同樣限制了資料規模。

因此,相對於從mongodb中抽出資料進行計算,在mongodb中利用彙總函式或者其他方法完成計算,避開nodejs自身限制的方案在可靠性和擴充性上都相對較為令人滿意。

 

mongodb支援類似SQL中的彙總函式,雖然文法不通,不過基本原理類似。

mongodb內建的介面中,aggregate被用來實現彙總查詢:

rec = db.LIBRARY.aggregate([{    $match: {        date: {            $gte: ‘2220832129000‘,            $lte: ‘3330918529000‘        }    }}, {    $group: {        _id: ‘$book_id‘,        maxScience: {            $max: ‘$shelf.science‘        },        maxMath: {            $max: ‘$data.math‘        },        avgAlgebra: {            $avg: ‘$data.algebra‘        }    }}])

在$group中可以利用各種運算子實現各種彙總運算。

如果目的是產生欄位不多的簡單資料結構,彙總運算幾乎可以一步到位。

需要注意的是在沒有格式轉換的情況下,js對於字串和數位區分很模糊。如果對字串變數使用max函數,出現的結果會是"999" > "1234"。如果mongodb內部資料格式不規範,可能得不到理想的結果。

 

對於複雜的計算,可以使用mapReduce方法。

mongodb的原生方法中包括了mapReduce方法,遍曆所有符合query條件的資料,對於每一條抽取到的資料,通過map方法提出索引值對,在收到的鍵發生變化時,將目前為止當前鍵的所有值儲存在一個數組中。

對於reduce方法觸發的時機,是在遍曆結果集,鍵發生變化時觸發,還是遍曆結束後,對新的索引值對遍曆執行reduce方法,這個目前還不能確定。

 

傳遞給reduce方法的參數包括鍵和一個儲存目前為止當前鍵的所有值的數組,reduce處理結束後,返回處理結果的統計結果,mapReduce過程結束。

 

mapReduce是個功能很強大的方法,目前我只能將接觸到的內容記錄下來,等待以後慢慢完善。

 首先,是最核心的map方法和reduce方法。

※ map方法

處理query條件抽取的結果集,對於每一條mongodb的記錄,都會執行一次map方法。

map方法一般不需要傳入參數,在方法體重,this指向當前處理的記錄,可以通過this.columnName方式調用記錄中的欄位。

map方法不需要傳回值,在方法體中,調用內建的emit方法,以emit(key, val)的形式向mapReduce記憶體中傳遞一組索引值對。索引值對的格式很自由,即使在目前記錄中不存在的變數,只要符合文法,同樣可以正常emit傳出。網上的例子裡,大部分emit方法中的value值都是數字,或單變數,但其實emit傳遞的索引值可以是複雜的json甚至某個外部方法,配合對應的reduce方法,可以實現更為複雜也更有效功能。

 

※ reduce方法

reduce方法的調用時機目前還不確定,基礎原理是接收兩個參數,key和values。其中key是emit傳出的鍵,values是經過整合後,集中在同一個數組中的相同key的值,即使只有一個值,values也是數組形式儲存的。

在此過程之前,相同key的相同value並不會被合并,map reduce概念說明中提到的詞頻統計的執行個體,是在map reduce過程完成後才產生了被合并的結果,而在reduce方法真正執行之前,相同key的相同value應該會保持emit時的狀態。

在reduce方法中,遍曆values數組,根據emit方法中value對應的結構,對有共同特性的結果進行統一處理,最後返回結果,在mapReduce方法的傳回值中,當前key對應的值就是reduce方法返回的結果。可以總結為mapReduce方法的返回結果就是 emit中的key: reduce中的傳回值 形式的json格式索引值對組。

在mongodb自己的js介面中,mapReduce方法的直接傳回值是方法的結果統計:

> rec = db.DATA.mapReduce(m, r, {query:{time:{$gte:‘1450832129000‘}}, sort: {id:1}, out:"result"})
{
"result" : "result",
"timeMillis" : 50948,
"counts" : {
"input" : 490672,
"emit" : 490672,
"reduce" : 4931,
"output" : 26
},
"ok" : 1
}
>

使用這種介面,如果需要查看詳細的計算結果就需要設定mapReduce方法的out參數。

out參數的值是字串時,返回的結果中result屬性就是該字串的值,如果只需要查看統計結果,這樣也就夠了。

如果需要緩衝計算結果,就需要將out參數的值設定為{<option>:"暫存資料表名"}的json結構。mapReduce的計算結果會存在mongodb的暫存資料表中,可以通過find方法查看。

在out參數值的json結構中,<option>定義的是對暫存資料表中相同的key的處理方式,一共有三種:

replace 使用當前reduce結果替換暫存資料表中存在的結果

merge 當前reduce結果的key在暫存資料表中不存在時,將reduce結果存入暫存資料表,如果存在相同key,直接使用當前key的值替換暫存資料表中相同key的值

reduce 如果當前key在暫存資料表中存在,則對當前結果和已存在結果進行map reduce,重新調用map方法與reduce方法,將結果整合。

 

這裡需要注意的是,quey結果集較大時,可能出現對同一個key多次reduce的情況,這時需要設定out的整合方法為reduce,否則暫存資料表中儲存的將只是其中一次reduce的結果,而非所有記錄的reduce處理結果。在這種情況下,最好保持reduce方法的傳回值結構與map方法中emit的value結構相同,使後續mapReduce可以正常執行相同的map方法與reduce方法。

 

這次使用的並不是mongodb自己的js介面,而是mongoose,作為第三方mongodb外掛程式,使用起來比原生的要相對方便一些。

mongoose的model.mapReduce方法接收兩個參數:mapReduce結構設定對象、回呼函數(因為是非同步方法呼叫)

在mapReduce對象中,mapReduceObj.map指定map方法,mapReduceObj.reduce指定reduce方法,對於out參數,mongoose的mapReduce方法預設設定為{inline: 1},以js的json對象格式返回計算結果,預設對相同key的計算結果執行reduce方法,如果預期結果規模不大,就不需要像原生方法那樣再設定暫存資料表。

在map方法和reduce方法中如果需要使用外部的js變數,可以設定mapReduceObj.scope({key:外部變數,...}),在map或reduce方法中,直接使用定義好的key,就可以取到外部變數的值。

 

※ mapReduce的最佳化

對於處理大量資料的方法,在query後將結果集排序,盡量保證在執行map方法時相同的key連續出現,減少reduce的次數,可以顯著提升mapReduce的效率。這裡要注意,由於調用了sort,最好將key值涉及的mongodb欄位加上聯合或獨立索引,避免mongodb引擎使用預設sort方法產生錯誤。

 

還可以通過外部變數,過濾emit傳出的結果,只保留需要的資料,減少冗餘計算。

如果使用的語言支援,還可以考慮多線程方式執行,mapReduce方法的limit參數與skip參數,可以很方便的將結果集分塊。

 

另外,最近看蝴蝶書,裡邊對於遞迴的解釋讓我對mapReduce方法的實現有了些感想,mapReduce中,reduce方法使用了類似遞迴的概念,從結果看輸入,就是將輸入的資料集合根據索引值的不同,分成若干塊,對每一塊再分別調用reduce方法,逐層遞迴,直到每一塊的內容都是一條單獨的記錄,無法繼續分割為止。相同的map&reduce方法的遞迴調用。

 

關於mongodb的mapReduce

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.