MapReduce應(yīng)該算是MongoDB操作中比較復(fù)雜的了,自己開始理解的時候還是動了動腦子的,所以記錄在此!
命令語法:詳細(xì)看
db.runCommand( { mapreduce : 字符串,集合名, map : 函數(shù),見下文 reduce : 函數(shù),見下文 [, query : 文檔,發(fā)往map函數(shù)前先給過渡文檔] [, sort : 文檔,發(fā)往map函數(shù)前先給文檔排序] [, limit : 整數(shù),發(fā)往map函數(shù)的文檔數(shù)量上限] [, out : 字符串,統(tǒng)計結(jié)果保存的集合] [, keeptemp: 布爾值,鏈接關(guān)閉時臨時結(jié)果集合是否保存] [, finalize : 函數(shù),將reduce的結(jié)果送給這個函數(shù),做最后的處理] [, scope : 文檔,js代碼中要用到的變量] [, jsMode : 布爾值,是否減少執(zhí)行過程中BSON和JS的轉(zhuǎn)換,默認(rèn) true ] //注:false時 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可處理非常大的mapreduce,<br> //true時BSON-->js-->map-->reduce-->BSON [, verbose : 布爾值,是否產(chǎn)生更加詳細(xì)的服務(wù)器日志,默認(rèn) true ] } ); |
測試數(shù)據(jù):
現(xiàn)在我要統(tǒng)計同一age的name,也就是像如下的結(jié)果:
{age:0,names:["name_6","name_12","name_18"]}
{age:1,names:["name_1","name_7","name_13","name_19"]}
......
第一步是寫映射(Map)函數(shù),可以簡單的理解成分組吧~
var m=function(){
emit(this.age,this.name);
}
emit的第一個參數(shù)是key,就是分組的依據(jù),這是自然是age了,后一個是value,可以是要統(tǒng)計的數(shù)據(jù),下面會說明,value可以是JSON對象。
這樣m就會把送過來的數(shù)據(jù)根據(jù)key分組了,可以想象成如下結(jié)構(gòu):
第一組
{key:0,values: ["name_6","name_12","name_18"]
第二組
{key:1,values: ["name_1","name_7","name_13","name_19"]
......
組中的key其實就是age的值了,values是個數(shù)組,數(shù)組內(nèi)的成員都有相同的age!!。
第二步就是簡化了,編寫reduce函數(shù):
var r=function(key,values){
var ret={age:key,names:values};
return ret;
}
reduce函數(shù)會處理每一個分組,參數(shù)也正好是我們想像分組里的key和values。
這里reduce函數(shù)只是簡單的把key和values包裝了一下,因為不用怎么處理就是我們想要的結(jié)果了,然后返回一個對象。對象結(jié)構(gòu)正好和我們想象的相符!:
{age:對應(yīng)的age,names:[名字1,名字2..]}
最后,還可以編寫finalize函數(shù)對reduce的返回值做最后處理:
var f=function(key,rval){
if(key==0){
rval.msg="a new life,baby!";
}
return rval
}
這里的key還是上面的key,也就是還是age,rval是reduce的返回值,所以rval的一個實例如:{age:0,names:["name_6","name_12","name_18"]},
這里判斷 key 是不是 0 ,如果是而在 rval 對象上加 msg 屬性,顯然也可以判斷 rval.age==0,因為 key 和 rval.age 是相等的嘛!!
這里其他的選項就不說了,一看就知道。
運行:
結(jié)果導(dǎo)入到 t_age_names 集合中,查詢出來正是我想要的結(jié)果,看一下文檔的結(jié)構(gòu),不難發(fā)現(xiàn),_id 就是 key,value 就是處理后的返回值。
聯(lián)系客服