成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

MongoDB指南---17、MapReduce

pubdreamcc / 3317人閱讀

摘要:操作花費(fèi)的時(shí)間,單位是毫秒。處理完成后,會(huì)自動(dòng)將臨時(shí)集合的名字更改為你指定的集合名,這個(gè)重命名的過程是原子性的。作用域在這些函數(shù)內(nèi)部是不變的。上一篇文章指南聚合下一篇文章指南聚合命令

上一篇文章:MongoDB指南---16、聚合
下一篇文章:MongoDB指南---18、聚合命令

MapReduce是聚合工具中的明星,它非常強(qiáng)大、非常靈活。有些問題過于復(fù)雜,無法使用聚合框架的查詢語言來表達(dá),這時(shí)可以使用MapReduce。MapReduce使用JavaScript作為“查詢語言”,因此它能夠表達(dá)任意復(fù)雜的邏輯。然而,這種強(qiáng)大是有代價(jià)的:MapReduce非常慢,不應(yīng)該用在實(shí)時(shí)的數(shù)據(jù)分析中。
MapReduce能夠在多臺(tái)服務(wù)器之間并行執(zhí)行。它會(huì)將一個(gè)大問題分割為多個(gè)小問題,將各個(gè)小問題發(fā)送到不同的機(jī)器上,每臺(tái)機(jī)器只負(fù)責(zé)完成一部分工作。所有機(jī)器都完成時(shí),再將這些零碎的解決方案合并為一個(gè)完整的解決方案。
MapReduce需要幾個(gè)步驟。最開始是映射(map),將操作映射到集合中的每個(gè)文檔。這個(gè)操作要么“無作為”,要么“產(chǎn)生一些鍵和X個(gè)值”。然后就是中間環(huán)節(jié),稱作洗牌(shuffle),按照鍵分組,并將產(chǎn)生的鍵值組成列表放到對(duì)應(yīng)的鍵中?;?jiǎn)(reduce)則把列表中的值化簡(jiǎn)成一個(gè)單值。這個(gè)值被返回,然后接著進(jìn)行洗牌,直到每個(gè)鍵的列表只有一個(gè)值為止,這個(gè)值也就是最終結(jié)果。
下面會(huì)多舉幾個(gè)MapReduce的例子,這個(gè)工具非常強(qiáng)大,但也有點(diǎn)復(fù)雜。

 示例1:找出集合中的所有鍵

用MapReduce來解決這個(gè)問題有點(diǎn)大材小用,不過還是一種了解其機(jī)制的不錯(cuò)的方式。要是已經(jīng)知道MapReduce的原理,則直接跳到本節(jié)最后,看看MongoDB中MapReduce的使用注意事項(xiàng)。
MongoDB會(huì)假設(shè)你的模式是動(dòng)態(tài)的,所以并不跟蹤記錄每個(gè)文檔中的鍵。通常找到集合中所有文檔所有鍵的最好方式就是用MapReduce。在本例中,會(huì)記錄每個(gè)鍵出現(xiàn)了多少次。內(nèi)嵌文檔中的鍵就不計(jì)算了,但給map函數(shù)做個(gè)簡(jiǎn)單修改就能實(shí)現(xiàn)這個(gè)功能了。
在映射環(huán)節(jié),我們希望得到集合中每個(gè)文檔的所有鍵。map函數(shù)使用特別的emit函數(shù)“返回”要處理的值。emit會(huì)給MapReduce一個(gè)鍵(類似于前面$group所使用的鍵)和一個(gè)值。這里用emit將文檔某個(gè)鍵的計(jì)數(shù)(count)返回({count : 1})。我們想為每個(gè)鍵多帶帶計(jì)數(shù),所以為文檔中的每個(gè)鍵調(diào)用一次emit。this就是當(dāng)前映射文檔的引用:

> map = function() {
... for (var key in this) {
...     emit(key, {count : 1});
... }};

這樣就有了許許多多{count : 1}文檔,每一個(gè)都與集合中的一個(gè)鍵相關(guān)。這種由一個(gè)或多個(gè){count : 1}文檔組成的數(shù)組,會(huì)傳遞給reduce函數(shù)。reduce函數(shù)有兩個(gè)參數(shù),一個(gè)是key,也就是emit返回的第一個(gè)值,還有另外一個(gè)數(shù)組,由一個(gè)或者多個(gè)與鍵對(duì)應(yīng)的{count : 1}文檔組成。

> reduce = function(key, emits) {
... total = 0;
... for (var i in emits) {
...     total += emits[i].count;
... }
... return {"count" : total};
... }

reduce一定要能夠在之前的map階段或者前一個(gè)reduce階段的結(jié)果上反復(fù)執(zhí)行。所以reduce返回的文檔必須能作為reduce的第二個(gè)參數(shù)的一個(gè)元素。例如,x鍵映射到了3個(gè)文檔{count : 1,id : 1}、{count : 1,id : 2}和{count : 1,id : 3},其中id鍵只用于區(qū)分不同的文檔。MongoDB可能會(huì)這樣調(diào)用reduce:

> r1 = reduce("x", [{count : 1, id : 1}, {count : 1, id : 2}])
{count : 2}
> r2 = reduce("x", [{count : 1, id : 3}])
{count : 1}
> reduce("x", [r1, r2])
{count : 3}

不能認(rèn)為第二個(gè)參數(shù)總是初始文檔之一(比如{count:1})或者長(zhǎng)度固定。reduce應(yīng)該能處理emit文檔和其他reduce返回結(jié)果的各種組合。
總之,MapReduce函數(shù)可能會(huì)是下面這樣:

> mr = db.runCommand({"mapreduce" : "foo", "map" : map, "reduce" : reduce})
{
    "result" : "tmp.mr.mapreduce_1266787811_1",
    "timeMillis" : 12,
    "counts" : {
        "input" : 6
        "emit" : 14
        "output" : 5
    },
    "ok" : true
}

MapReduce返回的文檔包含很多與操作有關(guān)的元信息。

"result" : "tmp.mr.mapreduce_1266787811_1"

這是存放MapReduce結(jié)果的集合名。這是個(gè)臨時(shí)集合,MapReduce的連接關(guān)閉后它就被自動(dòng)刪除了。本章稍后會(huì)介紹如何指定一個(gè)好一點(diǎn)的名字以及將結(jié)果集合持久化。

"timeMillis" : 12

操作花費(fèi)的時(shí)間,單位是毫秒。

"counts" : { ... }

這個(gè)內(nèi)嵌文檔主要用作調(diào)試,其中包含3個(gè)鍵。

"input" : 6

發(fā)送到map函數(shù)的文檔個(gè)數(shù)。

"emit" : 14

在map函數(shù)中emit被調(diào)用的次數(shù)。

"output" : 5

結(jié)果集合中的文檔數(shù)量。
對(duì)結(jié)果集合進(jìn)行查詢會(huì)發(fā)現(xiàn)原有集合的所有鍵及其計(jì)數(shù):
···

db[mr.result].find()
{ "_id" : "_id", "value" : { "count" : 6 } }
{ "_id" : "a", "value" : { "count" : 4 } }
{ "_id" : "b", "value" : { "count" : 2 } }
{ "_id" : "x", "value" : { "count" : 1 } }
{ "_id" : "y", "value" : { "count" : 1 } }
···
這個(gè)結(jié)果集中的每個(gè)"_id"對(duì)應(yīng)原集合中的一個(gè)鍵,"value"鍵的值就是reduce的最終結(jié)果。
 示例2:網(wǎng)頁分類

假設(shè)有個(gè)網(wǎng)站,人們可以提交其他網(wǎng)頁的鏈接,比如reddit(http://www.reddit.com)。提交者可以給這個(gè)鏈接添加標(biāo)簽,表明主題,比如politics、geek或者icanhascheezburger??梢杂肕apReduce找出哪個(gè)主題最為熱門,熱門與否由最近的投票決定。
首先,建立一個(gè)map函數(shù),發(fā)出(emit)標(biāo)簽和一個(gè)基于流行度和新舊程度的值。

map = function() {
    for (var i in this.tags) {
        var recency = 1/(new Date() - this.date); 
        var score = recency * this.score;

        emit(this.tags[i], {"urls" : [this.url], "score" : score});
    }
};

現(xiàn)在就化簡(jiǎn)同一個(gè)標(biāo)簽的所有值,以得到這個(gè)標(biāo)簽的分?jǐn)?shù):

reduce = function(key, emits) {
    var total = {urls : [], score : 0}
    for (var i in emits) {
        emits[i].urls.forEach(function(url) {
            total.urls.push(url);
        }
        total.score += emits[i].score;
    }
    return total;
};

最終的集合包含每個(gè)標(biāo)簽的URL列表和表示該標(biāo)簽流行程度的分?jǐn)?shù)。

 MongoDB和MapReduce

前面兩個(gè)例子只用到了mapreduce、map和reduce鍵。這3個(gè)鍵是必需的,但是MapReduce命令還有很多可選的鍵。

"finalize" : function

可以將reduce的結(jié)果發(fā)送給這個(gè)鍵,這是整個(gè)處理過程的最后一步。

"keeptemp" : boolean

如果為值為true,那么在連接關(guān)閉時(shí)會(huì)將臨時(shí)結(jié)果集合保存下來,否則不保存。

"out" : string

輸出集合的名稱。如果設(shè)置了這選項(xiàng),系統(tǒng)會(huì)自動(dòng)設(shè)置keeptemp : true。

"query" : document

在發(fā)往map函數(shù)前,先用指定條件過濾文檔。

"sort" : document

在發(fā)往map前先給文檔排序(與limit一同使用非常有用)。

"limit" : integer

發(fā)往map函數(shù)的文檔數(shù)量的上限。

"scope" : document

可以在JavaScript代碼中使用的變量。

"verbose" : boolean

是否記錄詳細(xì)的服務(wù)器日志。

1. finalize函數(shù)

和group命令一樣,MapReduce也可以使用finalize函數(shù)作為參數(shù)。它會(huì)在最后一個(gè)reduce輸出結(jié)果后執(zhí)行,然后將結(jié)果存到臨時(shí)集合中。
返回體積比較大的結(jié)果集對(duì)MapReduce不是什么大不了的事情,因?yàn)樗幌駁roup那樣有4 MB的限制。然而,信息總是要傳遞出去的,通常來說,finalize是計(jì)算平均數(shù)、裁剪數(shù)組、清除多余信息的好時(shí)機(jī)。

2. 保存結(jié)果集合

默認(rèn)情況下,Mongo會(huì)在執(zhí)行MapReduce時(shí)創(chuàng)建一個(gè)臨時(shí)集合,集合名是系統(tǒng)選的一個(gè)不太常用的名字,將"mr"、執(zhí)行MapReduce的集合名、時(shí)間戳以及數(shù)據(jù)庫作業(yè)ID,用“.”連成一個(gè)字符串,這就是臨時(shí)集合的名字。結(jié)果產(chǎn)生形如mr.stuff.18234210220.2這樣的名字。MongoDB會(huì)在調(diào)用的連接關(guān)閉時(shí)自動(dòng)銷毀這個(gè)集合(也可以在用完之后手動(dòng)刪除)。如果希望保存這個(gè)集合,就要將keeptemp選項(xiàng)指定為true。
如果要經(jīng)常使用這個(gè)臨時(shí)集合,你可能想給它起個(gè)好點(diǎn)的名字。利用out選項(xiàng)(該選項(xiàng)接受字符串作為參數(shù))就可以為臨時(shí)集合指定一個(gè)易讀易懂的名字。如果用了out選項(xiàng),就不必指定keeptemp : true了,因?yàn)橹付╫ut選項(xiàng)時(shí)系統(tǒng)會(huì)將keeptemp設(shè)置為true。即便你取了一個(gè)非常好的名字,MongoDB也會(huì)在MapReduce的中間過程使用自動(dòng)生成的集合名。處理完成后,會(huì)自動(dòng)將臨時(shí)集合的名字更改為你指定的集合名,這個(gè)重命名的過程是原子性的。也就是說,如果多次對(duì)同一個(gè)集合調(diào)用MapReduce,也不會(huì)在操作中遇到集合不完整的情況。
MapReduce產(chǎn)生的集合就是一個(gè)普通的集合,在這個(gè)集合上執(zhí)行MapReduce完全沒有問題,或者在前一個(gè)MapReduce的結(jié)果上執(zhí)行MapReduce也沒有問題,如此往復(fù)直到無窮都沒問題!

3. 對(duì)文檔子集執(zhí)行MapReduce

有時(shí)需要對(duì)集合的一部分執(zhí)行MapReduce。只需在傳給map函數(shù)前使用查詢對(duì)文檔進(jìn)行過濾就好了。
每個(gè)傳遞給map函數(shù)的文檔都要先反序列化,從BSON對(duì)象轉(zhuǎn)換為JavaScript對(duì)象,這個(gè)過程非常耗時(shí)。如果事先知道只需要對(duì)集合的一部分文檔執(zhí)行MapReduce,那么在map之前先對(duì)文檔進(jìn)行過濾可以極大地提高map速度??梢酝ㄟ^"query"、"limit"和"sort"等鍵對(duì)文檔進(jìn)行過濾。
"query"鍵的值是一個(gè)查詢文檔。通常查詢返回的結(jié)果會(huì)傳遞給map函數(shù)。例如,有一個(gè)做跟蹤分析的應(yīng)用程序,現(xiàn)在我們需要上周的總結(jié)摘要,只要使用如下命令對(duì)上周的文檔執(zhí)行MapReduce就好了:

> db.runCommand({"mapreduce" : "analytics", "map" : map, "reduce" : reduce,
                 "query" : {"date" : {"$gt" : week_ago}}})

sort選項(xiàng)和limit一起使用時(shí)通常能夠發(fā)揮非常大的作用。limit也可以多帶帶使用,用來截取一部分文檔發(fā)送給map函數(shù)。
如果在上個(gè)例子中想分析最近10 000個(gè)頁面的訪問次數(shù)(而不是最近一周的),就可以使用limit和sort:

> db.runCommand({"mapreduce" : "analytics", "map" : map, "reduce" : reduce,
                 "limit" : 10000, "sort" : {"date" : -1}})

query、limit、sort可以隨意組合,但是如果不使用limit的話,sort就不能有效發(fā)揮作用。

4. 使用作用域

MapReduce可以為map、reduce、finalize函數(shù)都采用一種代碼類型。但多數(shù)語言里,可以指定傳遞代碼的作用域。然而MapReduce會(huì)忽略這個(gè)作用域。它有自己的作用域鍵"scope",如果想在MapReduce中使用客戶端的值,則必須使用這個(gè)參數(shù)。可以用“變量名 : 值”這樣的普通文檔來設(shè)置該選項(xiàng),然后在map、reduce和finalize函數(shù)中就能使用了。作用域在這些函數(shù)內(nèi)部是不變的。例如,上一節(jié)的例子使用1/(newDate() - this.date)計(jì)算頁面的新舊程度。可以將當(dāng)前日期作為作用域的一部分傳遞進(jìn)去:

> db.runCommand({"mapreduce" : "webpages", "map" : map, "reduce" : reduce,
                 "scope" : {now : new Date()}})

這樣,在map函數(shù)中就能計(jì)算1/(now - this.date)了。

5. 獲得更多的輸出

還有個(gè)用于調(diào)試的詳細(xì)輸出選項(xiàng)。如果想看看MapReduce的運(yùn)行過程,可以將"verbose"指定為true。
也可以用print把map、reduce、finalize過程中的信息輸出到服務(wù)器日志上。

上一篇文章:MongoDB指南---16、聚合
下一篇文章:MongoDB指南---18、聚合命令

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/44115.html

相關(guān)文章

  • MongoDB指南---17MapReduce

    摘要:操作花費(fèi)的時(shí)間,單位是毫秒。處理完成后,會(huì)自動(dòng)將臨時(shí)集合的名字更改為你指定的集合名,這個(gè)重命名的過程是原子性的。作用域在這些函數(shù)內(nèi)部是不變的。上一篇文章指南聚合下一篇文章指南聚合命令 上一篇文章:MongoDB指南---16、聚合下一篇文章:MongoDB指南---18、聚合命令 MapReduce是聚合工具中的明星,它非常強(qiáng)大、非常靈活。有些問題過于復(fù)雜,無法使用聚合框架的查詢語言...

    jonh_felix 評(píng)論0 收藏0
  • MongoDB指南---16、聚合

    摘要:將返回結(jié)果限制為前個(gè)。所以,聚合的結(jié)果必須要限制在以內(nèi)支持的最大響應(yīng)消息大小。包含字段和排除字段的規(guī)則與常規(guī)查詢中的語法一致。改變字符大小寫的操作,只保證對(duì)羅馬字符有效。只對(duì)羅馬字符組成的字符串有效。 上一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件下一篇文章:MongoDB指南---17、MapReduce 如果你有數(shù)據(jù)存儲(chǔ)在Mon...

    Keagan 評(píng)論0 收藏0
  • MongoDB指南---16、聚合

    摘要:將返回結(jié)果限制為前個(gè)。所以,聚合的結(jié)果必須要限制在以內(nèi)支持的最大響應(yīng)消息大小。包含字段和排除字段的規(guī)則與常規(guī)查詢中的語法一致。改變字符大小寫的操作,只保證對(duì)羅馬字符有效。只對(duì)羅馬字符組成的字符串有效。 上一篇文章:MongoDB指南---15、特殊的索引和集合:地理空間索引、使用GridFS存儲(chǔ)文件下一篇文章:MongoDB指南---17、MapReduce 如果你有數(shù)據(jù)存儲(chǔ)在Mon...

    _Zhao 評(píng)論0 收藏0
  • MongoDB指南---18、聚合命令

    摘要:上一篇文章指南下一篇文章為在集合上執(zhí)行基本的聚合任務(wù)提供了一些命令。也可以給傳遞一個(gè)查詢文檔,會(huì)計(jì)算查詢結(jié)果的數(shù)量對(duì)分頁顯示來說總數(shù)非常必要共個(gè),目前顯示個(gè)。使用時(shí)必須指定集合和鍵。指定要進(jìn)行分組的集合。 上一篇文章:MongoDB指南---17、MapReduce下一篇文章: MongoDB為在集合上執(zhí)行基本的聚合任務(wù)提供了一些命令。這些命令在聚合框架出現(xiàn)之前就已經(jīng)存在了,現(xiàn)在(大多...

    why_rookie 評(píng)論0 收藏0
  • MongoDB指南---18、聚合命令

    摘要:上一篇文章指南下一篇文章為在集合上執(zhí)行基本的聚合任務(wù)提供了一些命令。也可以給傳遞一個(gè)查詢文檔,會(huì)計(jì)算查詢結(jié)果的數(shù)量對(duì)分頁顯示來說總數(shù)非常必要共個(gè),目前顯示個(gè)。使用時(shí)必須指定集合和鍵。指定要進(jìn)行分組的集合。 上一篇文章:MongoDB指南---17、MapReduce下一篇文章: MongoDB為在集合上執(zhí)行基本的聚合任務(wù)提供了一些命令。這些命令在聚合框架出現(xiàn)之前就已經(jīng)存在了,現(xiàn)在(大多...

    raoyi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<