MongoDB MapReduce 聚合操作

MongoDB的聚合操作主要是對數(shù)據(jù)的批量處理箕宙。一般都是將記錄按條件分組之后進(jìn)行一系列求最大值,最小值逾苫,平均值的簡單操作卿城,也可以對記錄進(jìn)行數(shù)據(jù)統(tǒng)計(jì),數(shù)據(jù)挖掘的復(fù)雜操作铅搓。聚合操作的輸入是集中的文檔瑟押,輸出可以是一個文檔也可以是多個文檔。

MongoDB 提供了三種強(qiáng)大的聚合操作:

Pipeline查詢速度快于MapReduce星掰,但是MapReduce的強(qiáng)大之處在于能夠在多臺Server上并行執(zhí)行復(fù)雜的聚合邏輯多望。MongoDB不允許Pipeline的單個聚合操作占用過多的系統(tǒng)內(nèi)存嫩舟,如果一個聚合操作消耗20%以上的內(nèi)存,那么MongoDB直接停止操作怀偷,并向客戶端輸出錯誤消息家厌。

本篇主要講解 MapReduce 編程模型。MapReduce是一種計(jì)算模型椎工,簡單的說就是將大批量的工作(數(shù)據(jù))分解(MAP)執(zhí)行饭于,然后再將結(jié)果合并成最終結(jié)果(REDUCE)。

一维蒙、MapReduce 命令

MapReduce 的基本語法如下:

>db.collection.mapReduce(
   function() {emit(key,value);},  //map 函數(shù)
   function(key,values) {return reduceFunction},   //reduce 函數(shù)
   {
      out: collection,
      query: document,
      sort: document,
      limit: number,
      finalize: <function>,
      scope: <document>,
      jsMode: <boolean>,
      verbose: <boolean>
   }
)

使用 MapReduce 要實(shí)現(xiàn)兩個函數(shù) Map 函數(shù)和 Reduce 函數(shù),Map 函數(shù)調(diào)用 emit(key, value), 遍歷 collection 中所有的記錄, 將 key 與 value 傳遞給 Reduce 函數(shù)進(jìn)行處理掰吕。
參數(shù)說明:

  • map:是JavaScript 函數(shù),負(fù)責(zé)將每一個輸入文檔轉(zhuǎn)換為零或多個文檔颅痊,通過key進(jìn)行分組畴栖,生成鍵值對序列,作為 reduce 函數(shù)參數(shù)
  • reduce:是JavaScript 函數(shù),對map操作的輸出做合并的化簡的操作(將key-values變成key-value八千,也就是把values數(shù)組變成一個單一的值value)
  • out:統(tǒng)計(jì)結(jié)果存放集合 (不指定則使用臨時集合,在客戶端斷開后自動刪除)。
  • query: 一個篩選條件燎猛,只有滿足條件的文檔才會調(diào)用map函數(shù)恋捆。(query。limit重绷,sort可以隨意組合)
  • sort: 和limit結(jié)合的sort排序參數(shù)(也是在發(fā)往map函數(shù)前給文檔排序)沸停,可以優(yōu)化分組機(jī)制
  • limit: 發(fā)往map函數(shù)的文檔數(shù)量的上限(要是沒有l(wèi)imit,單獨(dú)使用sort的用處不大)
  • finalize:可以對reduce輸出結(jié)果再一次修改昭卓,跟group的finalize一樣愤钾,不過MapReduce沒有g(shù)roup的4MB文檔的輸出限制
  • scope:向map、reduce候醒、finalize導(dǎo)入外部變量
  • verbose:是否包括結(jié)果信息中的時間信息能颁,默認(rèn)為fasle

關(guān)于MapReduce的工作流程如下:


工作流程

在集合 orders 中查找 status:"A" 的數(shù)據(jù),并根據(jù) cust_id 來分組倒淫,并計(jì)算 amount 的總和伙菊。

二、使用示例

對以下結(jié)構(gòu)的文檔進(jìn)行統(tǒng)計(jì)敌土。統(tǒng)計(jì)每個用戶的文章數(shù)量镜硕。

>db.col.find()
{
    "_id" : ObjectId("5c09dfcde354b306e46af7f3"),
    "bookname" : "Java 8 實(shí)戰(zhàn)",
    "author" : "simon",
    "status" : "active"
},
{
    "_id" : ObjectId("5c09dfdee354b306e46af7f4"),
    "bookname" : "MongoDB權(quán)威指南",
    "author" : "simon",
    "status" : "active"
},
{
    "_id" : ObjectId("5c09dfffe354b306e46af7f5"),
    "bookname" : "MyBatis 實(shí)戰(zhàn)",
    "author" : "simon",
    "status" : "disabled"
},
{
    "_id" : ObjectId("5c09e016e354b306e46af7f6"),
    "bookname" : "MyBatis 從入門到具精通",
    "author" : "Aaron",
    "status" : "disabled"
},
{
    "_id" : ObjectId("5c09e02ce354b306e46af7f7"),
    "bookname" : "Spring Boot 2.0",
    "author" : "Aaron",
    "status" : "active"
},
{
    "_id" : ObjectId("5c09e037e354b306e46af7f8"),
    "bookname" : "Spring Cloud",
    "author" : "Aaron",
    "status" : "active"
},
{
    "_id" : ObjectId("5c09e038e354b306e46af7f9"),
    "bookname" : "Spring Cloud",
    "author" : "Aaron",
    "status" : "active"
}

將在 col 集合中使用 mapReduce 函數(shù)來選取已發(fā)布的文章(status:"active"),并通過author分組返干,計(jì)算每個用戶的文章數(shù)

>db.col.mapReduce(
   function() { emit(this.author,1); },
   function(key, values) {return Array.sum(values)},
      {  
         query:{status:"active"},  
         out:"total"
      }
)
{
    "result" : "total",
    "timeMillis" : 422.0,
    "counts" : {
        "input" : 5,
        "emit" : 5,
        "reduce" : 2,
        "output" : 2
    },
    "ok" : 1.0,
    "_o" : {
        "result" : "total",
        "timeMillis" : 422,
        "counts" : {
            "input" : 5,
            "emit" : 5,
            "reduce" : 2,
            "output" : 2
        },
        "ok" : 1.0
    },
    "_keys" : [
        "result",
        "timeMillis",
        "counts",
        "ok"
    ],
    "_db" : {
        "_mongo" : {
            "slaveOk" : true,
            "host" : "192.168.10.58:27017",
            "defaultDB" : "test",
            "_readMode" : "commands",
            "_writeMode" : "commands"
        },
        "_name" : "ibase_dev"
    },
    "_coll" : {
        "_mongo" : {
            "slaveOk" : true,
            "host" : "192.168.10.58:27017",
            "defaultDB" : "test",
            "_readMode" : "commands",
            "_writeMode" : "commands"
        },
        "_db" : {
            "_mongo" : {
                "slaveOk" : true,
                "host" : "192.168.10.58:27017",
                "defaultDB" : "test",
                "_readMode" : "commands",
                "_writeMode" : "commands"
            },
            "_name" : "ibase_dev"
        },
        "_shortName" : "total",
        "_fullName" : "ibase_dev.total"
    }
}

從結(jié)果中可以看出兴枯,一共有5個文檔服務(wù){status:'active'}的文檔,在map函數(shù)中生成了5個鍵值對文檔矩欠,最后使用reduce函數(shù)將相同的鍵值分為 2 組财剖。

具體參數(shù)說明:

  • result:儲存結(jié)果的collection的名字,這是個臨時集合悠夯,MapReduce的連接關(guān)閉后自動就被刪除了。
  • timeMillis:執(zhí)行花費(fèi)的時間峰伙,毫秒為單位
  • input:滿足條件被發(fā)送到map函數(shù)的文檔個數(shù)
  • emit:在map函數(shù)中emit被調(diào)用的次數(shù)疗疟,也就是所有集合中的數(shù)據(jù)總量
  • ouput:結(jié)果集合中的文檔個數(shù)(count對調(diào)試非常有幫助),out: { inline: 1 }不會創(chuàng)建集合,結(jié)果在內(nèi)存中
  • ok:是否成功瞳氓,成功為1
  • err:如果失敗策彤,這里可以有失敗原因,不過從經(jīng)驗(yàn)上來看匣摘,原因比較模糊店诗,作用不大

查看執(zhí)行結(jié)果:

>db.total.find()
{
    "_id" : "Aaron",
    "value" : 3.0
},
{
    "_id" : "simon",
    "value" : 2.0
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市音榜,隨后出現(xiàn)的幾起案子庞瘸,更是在濱河造成了極大的恐慌,老刑警劉巖赠叼,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件擦囊,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘴办,警方通過查閱死者的電腦和手機(jī)瞬场,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來涧郊,“玉大人贯被,你說我怎么就攤上這事∽彼遥” “怎么了彤灶?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長批旺。 經(jīng)常有香客問我幌陕,道長,這世上最難降的妖魔是什么汽煮? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任苞轿,我火速辦了婚禮,結(jié)果婚禮上逗物,老公的妹妹穿的比我還像新娘搬卒。我一直安慰自己,他們只是感情好翎卓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布契邀。 她就那樣靜靜地躺著,像睡著了一般失暴。 火紅的嫁衣襯著肌膚如雪坯门。 梳的紋絲不亂的頭發(fā)上微饥,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音古戴,去河邊找鬼欠橘。 笑死,一個胖子當(dāng)著我的面吹牛现恼,可吹牛的內(nèi)容都是我干的肃续。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼叉袍,長吁一口氣:“原來是場噩夢啊……” “哼始锚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起喳逛,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤瞧捌,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后润文,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姐呐,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年典蝌,在試婚紗的時候發(fā)現(xiàn)自己被綠了曙砂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡赠法,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乔夯,到底是詐尸還是另有隱情砖织,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布末荐,位于F島的核電站侧纯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏甲脏。R本人自食惡果不足惜眶熬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望块请。 院中可真熱鬧娜氏,春花似錦、人聲如沸墩新。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽海渊。三九已至绵疲,卻和暖如春哲鸳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背盔憨。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工徙菠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人郁岩。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓婿奔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親驯用。 傳聞我的和親對象是個殘疾皇子脸秽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

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