MongoDB:MapReduce基礎(chǔ)及實(shí)例-創(chuàng)新互聯(lián)

背景

    MapReduce是個(gè)非常靈活和強(qiáng)大的數(shù)據(jù)聚合工具。它的好處是可以把一個(gè)聚合任務(wù)分解為多個(gè)小的任務(wù),分配到多服務(wù)器上并行處理。

成都創(chuàng)新互聯(lián)公司是網(wǎng)站建設(shè)專家,致力于互聯(lián)網(wǎng)品牌建設(shè)與網(wǎng)絡(luò)營(yíng)銷,專業(yè)領(lǐng)域包括網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站制作、電商網(wǎng)站制作開發(fā)、微信平臺(tái)小程序開發(fā)、微信營(yíng)銷、系統(tǒng)平臺(tái)開發(fā),與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開發(fā)公司不同,我們的整合解決方案結(jié)合了恒基網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷的理念,并將策略和執(zhí)行緊密結(jié)合,且不斷評(píng)估并優(yōu)化我們的方案,為客戶提供全方位的互聯(lián)網(wǎng)品牌整合方案!

MongoDB也提供了MapReduce,當(dāng)然查詢語肯定是JavaScript。MongoDB中的MapReduce主要有以下幾階段:

  1. Map:把一個(gè)操作Map到集合中的每一個(gè)文檔

  2. Shuffle: 根據(jù)Key分組對(duì)文檔,并且為每個(gè)不同的Key生成一系列(>=1個(gè))的值表(List of values)。

  3. Reduce: 處理值表中的元素,直到值表中只有一個(gè)元素。然后將值表返回到Shuffle過程,循環(huán)處理,直到每個(gè)Key只對(duì)應(yīng)一個(gè)值表,并且此值表中只有一個(gè)元素,這就是MR的結(jié)果。

  4. Finalize:此步驟不是必須的。在得到MR最終結(jié)果后,再進(jìn)行一些數(shù)據(jù)“修剪”性質(zhì)的處理。

MongoDB中使用emit函數(shù)向MapReduce提供Key/Value對(duì)。

Reduce函數(shù)接受兩個(gè)參數(shù):Key,emits. Key即為emit函數(shù)中的Key。 emits是一個(gè)數(shù)組,它的元素就是emit函數(shù)提供的Value。

Reduce函數(shù)的返回結(jié)果必須要能被Map或者Reduce重復(fù)使用,所以返回結(jié)果必須與emits中元素結(jié)構(gòu)一致。

Map或者Reduce函數(shù)中的this關(guān)鍵字,代表當(dāng)前被Mapping文檔。

實(shí)例

 測(cè)試數(shù)據(jù): 這個(gè)集合是三個(gè)用戶購買的產(chǎn)品和產(chǎn)品價(jià)格的數(shù)據(jù)。

CodeCodefor(var i=0;i<1000;i++){ 
var rID=Math.floor(Math.random()*10); 
var priceparseFloat((Math.random()*10).toFixed(2)); 
if(rID<4){ 
    db.test.insert({"user":"Joe","sku":rID,"price":price}); 
} 
else if(rID>=4 && rID<7)
{ 
   db.test.insert({"user":"Josh","sku":rID,"price":price}); 
} 
else {  
db.test.insert({"user":"Ken","sku":rID,"price":price}); 
     } 
}

 1. 每個(gè)用戶各購買了多少個(gè)產(chǎn)品?(單一Key做MR)

Code//SQL實(shí)現(xiàn)select user,count(sku) from test
group by user//MapReduce實(shí)現(xiàn)map=function (){
 emit(this.user,{count:1})
}

reduce=function (key,values){ var cnt=0;   
values.forEach(function(val){ cnt+=val.count;});  
return {"count":cnt};
}//MR結(jié)果存到集合mr1db.test.mapReduce(map,reduce,{out:"mr1"})//查看MR之后結(jié)果> db.mr1.find()
{ "_id" : "Joe", "value" : { "count" : 416 } }
{ "_id" : "Josh", "value" : { "count" : 287 } }
{ "_id" : "Ken", "value" : { "count" : 297 } }

2. 每個(gè)用戶不同的產(chǎn)品購買了多少個(gè)?(復(fù)合Key做MR)

Code//SQL實(shí)現(xiàn)select user,sku,count(*) from test
group by user,sku//MapReduce實(shí)現(xiàn)map=function (){
 emit({user:this.user,sku:this.sku},{count:1})
}

reduce=function (key,values){ var cnt=0;   
values.forEach(function(val){ cnt+=val.count;});  
return {"count":cnt};
}

db.test.mapReduce(map,reduce,{out:"mr2"})
> db.mr2.find()
{ "_id" : { "user" : "Joe", "sku" : 0 }, "value" : { "count" : 103 } }
{ "_id" : { "user" : "Joe", "sku" : 1 }, "value" : { "count" : 106 } }
{ "_id" : { "user" : "Joe", "sku" : 2 }, "value" : { "count" : 102 } }
{ "_id" : { "user" : "Joe", "sku" : 3 }, "value" : { "count" : 105 } }
{ "_id" : { "user" : "Josh", "sku" : 4 }, "value" : { "count" : 87 } }
{ "_id" : { "user" : "Josh", "sku" : 5 }, "value" : { "count" : 107 } }
{ "_id" : { "user" : "Josh", "sku" : 6 }, "value" : { "count" : 93 } }
{ "_id" : { "user" : "Ken", "sku" : 7 }, "value" : { "count" : 98 } }
{ "_id" : { "user" : "Ken", "sku" : 8 }, "value" : { "count" : 83 } }
{ "_id" : { "user" : "Ken", "sku" : 9 }, "value" : { "count" : 116 } }

3. 每個(gè)用戶購買的產(chǎn)品數(shù)量,總金額是多少?(復(fù)合Reduce結(jié)果處理)

Code//SQL實(shí)現(xiàn)select user,count(sku),sum(price) from test
group by user//MapReduce實(shí)現(xiàn)map=function (){
  emit(this.user,{amount:this.price,count:1})
}

reduce=function (key,values){ var res={amount:0,count:0}
values.forEach(function(val){ 
    res.amount+=val.amount;
    res.count+=val.count
});  
return res;
}

db.test.mapReduce(map,reduce,{out:"mr3"})

> db.mr3.find()
{ "_id" : "Joe", "value" : { "amount" : 2053.8899999999994, "count" : 395 } }
{ "_id" : "Josh", "value" : { "amount" : 1409.2600000000002, "count" : 292 } }
{ "_id" : "Ken", "value" : { "amount" : 1547.7700000000002, "count" : 313 } }

4. 在3中返回的amount的float精度需要改成兩位小數(shù),還需要得到商品的平均價(jià)格。(使用Finalize處理reduce結(jié)果集)

Code//SQL實(shí)現(xiàn)select user,cast(sum(price) as   decimal(10,   2)) as amount,count(sku) as [count],
cast((sum(price)/count(sku))  as decimal(10,2)) as avgPrice
from test
group by user//MapReduce實(shí)現(xiàn)map=function (){
  emit(this.user,{amount:this.price,count:1,avgPrice:0})
}

reduce=function (key,values){ var res={amount:0,count:0,avgPrice:0}
values.forEach(function(val){ 
    res.amount+=val.amount;
    res.count+=val.count
});  
return res;
}

finalizeFun=function (key,reduceResult){
 reduceResult.amount=(reduceResult.amount).toFixed(2);
 reduceResult.avgPrice=(reduceResult.amount/reduceResult.count).toFixed(2); return reduceResult;}

 db.test.mapReduce(map,reduce,{out:"mr4",finalize:finalizeFun})
> db.mr4.find()
{ "_id" : "Joe", "value" : { "amount" : "2053.89", "count" : 395, "avgPrice" : "5.20" } }
{ "_id" : "Josh", "value" : { "amount" : "1409.26", "count" : 292, "avgPrice" : "4.83" } }
{ "_id" : "Ken", "value" : { "amount" : "1547.77", "count" : 313, "avgPrice" : "4.94" } }

5. 統(tǒng)計(jì)單價(jià)大于6的SKU,每個(gè)用戶的購買數(shù)量.(篩選數(shù)據(jù)子集做MR)

 這個(gè)比較簡(jiǎn)單了,只需要將1.中調(diào)用MR時(shí)加上篩選查詢即可,其它不變.

Codedb.test.mapReduce(map,reduce,{query:{price:{"$gt":6}},out:"mr5"})

總結(jié)

  MongoDB中的MR工具非常強(qiáng)大,文中的例子只是基礎(chǔ)實(shí)例.結(jié)合Sharding后,多服務(wù)器并行做數(shù)據(jù)集合處理,才能真正顯現(xiàn)其能力.

  如果后續(xù)有時(shí)間,希望能總結(jié)和分享更多關(guān)于MongoDB,關(guān)于SQL Server的東西.

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

新聞標(biāo)題:MongoDB:MapReduce基礎(chǔ)及實(shí)例-創(chuàng)新互聯(lián)
路徑分享:http://bm7419.com/article12/iihgc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動(dòng)態(tài)網(wǎng)站、關(guān)鍵詞優(yōu)化、網(wǎng)站改版、響應(yīng)式網(wǎng)站、云服務(wù)器軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

小程序開發(fā)