下面的例子是在小資料下測試的,我嘗試在單機的千萬層級測試,等很久都沒結果...
資料有表:crawler.videos,表結構是: _id, playUrl, siteId...
只有_id是有索引的,siteId不同的值分別代表不同的網站。值有:1,2,3三個值。
現在要統計資料庫中每個網站的所含有的id數。就是相當於在mySql中select count(_id),siteId from videos group by siteId 的語句。
以siteId分組,統計各siteId所含有的id數。在mongo中,可以通過group函數來做,也可以通過mapReduce來做,現記錄兩種做法:
通過group()函數
文法:
db.coll.group(
{key: { fieldToGroup : true },
cond: { condition_where },
reduce: function(obj , prev) { logical_sentenct; },
initial: { initial_values }
});
對於上述的需求,可以這樣寫:
use crawler;
db.videos.group(
{key:{siteId:true},
reduce:function(obj,prev){ prev.count++;},
initial:{count:0}
});
現在說明一下:因為需求中沒條件限制,所以cond域就不用寫了。另外在reduce中,那個function函數可以提出外面寫,如:
r = function(obj,prev){
prev.count++};
db.videos.group(
{key:{siteId:true},
reduce: r,
initial:{count:0}
});
在mongoDB中,function()就相當於JavaScript的文法。
這裡需要注意的是,在reduce的function函數中,一定要有兩個參數(obj,prev),obj是當前遍曆的對象,
prev是彙總計數器[aggregation counter obj]。
上述命令的結果顯示是:
[
{
"siteId" : 1,
"count" : 188603
},
{
"siteId" : 3,
"count" : 2198
},
{
"siteId" : 2,
"count" : 210
}
]
通過MapReduce方法:
在mongo終端輸入:
m = function () {
emit(this.siteId, 1);
};
r = function (key, values) {
var total = 0;
for (var i = 0; i < values.length; i++) {
total += values[i];
}
return total;
};
res = db.videos.mapReduce(m,r);
db[res.result].find(); //顯示結果
上述的函數顯示每個siteId的總記錄數,結果如下:
{ "_id" : 1, "value" : 188603 }
{ "_id" : 2, "value" : 210 }
{ "_id" : 3, "value" : 2198 }
res = db.videos.mapReduce(m,r); 語句也可以這樣寫:
res = db.runCommand({
mapreduce:"videos",
map:m,
reduce:r});
若忘記把db.runCommand()的結果傳入res中,則可以在運行完runCommand命令的列印資訊裡找到
"result" : "tmp.mr.mapreduce_1291273572_8",之類的資訊,則表明結果儲存在
tmp.mr.mapreduce_1291273572_8的表中,在終端直接寫:
tmp.mr.mapreduce_1291273572_8.find()則會顯示結果。
最後db[res.result].drop(),把最後結果刪除。
Map函數中需要把emit()函數把結果傳給reduce函數。emit(key,value)中,key是value作為分組的key,
value的類型需要和reduce函數的values的類型一致。Map函數在傳給Reduce函數前,會合并相同key的value,
形成(key,values)的中間結果,並傳給reduce函數。
Reduce函數中對中間結果進行處理,並把最後結果存入result中。
在mapReduce中可以添加條件,如db.videos.mapReduce(m,r[,option...]) 或根據官方文檔的標準文法:
db.runCommand(
{ mapreduce : <collection>,
map : <mapfunction>,
reduce : <reducefunction>
[, query : <query filter object>]
[, sort : <sort the query. useful for optimization>]
[, limit : <number of objects to return from collection>]
[, out : <output-collection name>]
[, outType : ("normal"|"merge"|"reduce")] -- since 1.7.3
[, keeptemp: <true|false>]
[, finalize : <finalizefunction>]
[, scope : <object where fields go into javascript global scope >]
[, verbose : true]
}
);