MongoDB MapReduce

MapReduce 使用JavaScript作為“查詢語言”。因此它能夠表達
任意復(fù)雜的邏輯挫以。然而掐松,這種強大是有代價的:MapReduce非常慢,
不應(yīng)該實時的數(shù)據(jù)分析中

MapReduce能夠在多態(tài)服務(wù)器之間并行執(zhí)行抡句。它會將一個大問題分隔為多個小
問題杠愧,將各個小問題發(fā)送到不同的機器上殴蹄,每臺機器只負責(zé)完成一部分工作。
所有機器都完成時刺下,將這些零碎的解決方案合并稱為一個完整的解決方案稽荧。

MapReduce 需要幾個步驟。

  • 映射(map)
    將操作映射到集合中的每個文檔姨丈。這個操作要么“無作為”畅卓,要么“產(chǎn)生一些鍵和X個值”。

  • 洗牌(shuffle)
    按照鍵分組蟋恬,并將產(chǎn)生的鍵值組成列表放到對應(yīng)的鍵中翁潘。

  • 化簡(reduce)
    把列表中的值化簡成一個單值。這個值被返回歼争,然后接著進行洗牌拜马,直到每個鍵的列表只有
    一個值為止渗勘,這個值也就是最終的結(jié)果。

創(chuàng)造基礎(chǔ)數(shù)據(jù)

  for(var i=0; i< 100; i++){
    db.t.insert(
      {
         _id: i,
         "name": "user_"+i,
         "age" : NumberInt(Math.random() * 10)
         })
  }
  > db.t.find()
  { "_id" : 0, "name" : "user_0", "age" : 5 }
  { "_id" : 1, "name" : "user_1", "age" : 9 }
  { "_id" : 2, "name" : "user_2", "age" : 8 }
  { "_id" : 3, "name" : "user_3", "age" : 4 }
  { "_id" : 4, "name" : "user_4", "age" : 0 }
  { "_id" : 5, "name" : "user_5", "age" : 7 }
  { "_id" : 6, "name" : "user_6", "age" : 3 }
  { "_id" : 7, "name" : "user_7", "age" : 8 }
  { "_id" : 8, "name" : "user_8", "age" : 7 }
  { "_id" : 9, "name" : "user_9", "age" : 8 }
  { "_id" : 10, "name" : "user_10", "age" : 9 }
  { "_id" : 11, "name" : "user_11", "age" : 3 }
  { "_id" : 12, "name" : "user_12", "age" : 8 }
  { "_id" : 13, "name" : "user_13", "age" : 0 }
  { "_id" : 14, "name" : "user_14", "age" : 7 }
  { "_id" : 15, "name" : "user_15", "age" : 8 }
  { "_id" : 16, "name" : "user_16", "age" : 4 }
  { "_id" : 17, "name" : "user_17", "age" : 7 }
  { "_id" : 18, "name" : "user_18", "age" : 5 }
  { "_id" : 19, "name" : "user_19", "age" : 2 }
  Type "it" for more

統(tǒng)計age相同的名字

var map = function(){
  emit(this.age, this.name);
};

var reduce = function(key, values){
  var ret={ age: key, names: values };
  return ret;
};

var finalize = function(key, rval){
  if(key == 0){
    rval.msg = "a new life, baby!";
  }
  return rval;
};

db.runCommand({
  mapreduce: "t",
  map: map,
  reduce: reduce,
  finalize: finalize,
  out: "t_age_names"
});


> db.t_age_names.findOne({ _id: 0 })
{
    "_id" : 0,
    "value" : {
        "age" : 0,
        "names" : [
            "user_4",
            "user_13",
            "user_27",
            "user_30",
            "user_48",
            "user_55",
            "user_59",
            "user_63",
            "user_64",
            "user_67",
            "user_70",
            "user_74",
            "user_75",
            "user_95"
        ],
        "msg" : "a new life, baby!"
    }
};

age為0 的數(shù)據(jù)個數(shù)為14個俩莽。

> db.t_age_names.findOne({ _id: 1 })
{
    "_id" : 1,
    "value" : {
        "age" : 1,
        "names" : [
            "user_25",
            "user_28",
            "user_32",
            "user_54",
            "user_61",
            "user_85"
        ]
    }
}

age為1的數(shù)據(jù)個數(shù)為6個。

> db.t_age_names.findOne({ _id: 9 })
{
    "_id" : 9,
    "value" : {
        "age" : 9,
        "names" : [
            "user_1",
            "user_10",
            "user_40",
            "user_78",
            "user_97"
        ]
    }
}

age 為9的數(shù)據(jù)個數(shù)為5個扮超。

檢測 age 相同的個數(shù)

  var count_map = function(){
    emit(this.age, 1);
  };

  var count_reduce = function(key, values){
    total = 0;
    for(var i in  values ){
      total += 1;
    }
    return { age: key, total: total }
  };

  db.runCommand({
    mapreduce: "t",
    map: count_map,
    reduce: count_reduce,
    out: "t_age_count"
  });

  {
    "result" : "t_age_count",
    "timeMillis" : 5,
    "counts" : {
        "input" : 100,
        "emit" : 100,
        "reduce" : 10,
        "output" : 10
    },
    "ok" : 1
  }

input 其中input 表示發(fā)送到map函數(shù)的文檔個數(shù)取刃。
emit 在map函數(shù)中emit 被調(diào)用的次數(shù)。
output 結(jié)果集合中的文檔數(shù)量出刷。

最終統(tǒng)計結(jié)果如下

  > db.t_age_count.find()
  { "_id" : 0, "value" : { "age" : 0, "total" : 14 } }
  { "_id" : 1, "value" : { "age" : 1, "total" : 6 } }
  { "_id" : 2, "value" : { "age" : 2, "total" : 11 } }
  { "_id" : 3, "value" : { "age" : 3, "total" : 7 } }
  { "_id" : 4, "value" : { "age" : 4, "total" : 16 } }
  { "_id" : 5, "value" : { "age" : 5, "total" : 11 } }
  { "_id" : 6, "value" : { "age" : 6, "total" : 10 } }
  { "_id" : 7, "value" : { "age" : 7, "total" : 12 } }
  { "_id" : 8, "value" : { "age" : 8, "total" : 8 } }
  { "_id" : 9, "value" : { "age" : 9, "total" : 5 } }

MapReduce 可選鍵

  • finalize: function

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

  • keeptmp:boolean

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

  • out:string

    輸出集合的名稱屁柏。如果設(shè)置了這選項啦膜,系統(tǒ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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末僧家,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子裸删,更是在濱河造成了極大的恐慌八拱,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涯塔,死亡現(xiàn)場離奇詭異肌稻,居然都是意外死亡,警方通過查閱死者的電腦和手機匕荸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門爹谭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人榛搔,你說我怎么就攤上這事诺凡。” “怎么了践惑?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵腹泌,是天一觀的道長。 經(jīng)常有香客問我尔觉,道長凉袱,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任穷娱,我火速辦了婚禮绑蔫,結(jié)果婚禮上运沦,老公的妹妹穿的比我還像新娘泵额。我一直安慰自己配深,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布嫁盲。 她就那樣靜靜地躺著篓叶,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羞秤。 梳的紋絲不亂的頭發(fā)上缸托,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音瘾蛋,去河邊找鬼俐镐。 笑死,一個胖子當著我的面吹牛哺哼,可吹牛的內(nèi)容都是我干的佩抹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼取董,長吁一口氣:“原來是場噩夢啊……” “哼棍苹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起茵汰,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤枢里,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后蹂午,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栏豺,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年豆胸,在試婚紗的時候發(fā)現(xiàn)自己被綠了奥洼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡配乱,死狀恐怖溉卓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情搬泥,我是刑警寧澤桑寨,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站忿檩,受9級特大地震影響尉尾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜燥透,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一沙咏、第九天 我趴在偏房一處隱蔽的房頂上張望辨图。 院中可真熱鬧,春花似錦肢藐、人聲如沸故河。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鱼的。三九已至,卻和暖如春痘煤,著一層夾襖步出監(jiān)牢的瞬間凑阶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工衷快, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宙橱,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓蘸拔,卻偏偏與公主長得像师郑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子都伪,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

推薦閱讀更多精彩內(nèi)容