我的Mongo数据库集合中有400,000个数据。每个文档都有计数(数字)。我想读取这些文档并添加所有数字以获得总数。我使用Node.js和mongoose获取Mongo DB Collection数据然后计算总使用量for-loop.it需要大约两分钟。我想在一秒钟内接受它。有没有办法加速这个过程?。我发现mapreduce可以加速这个。加速这个过程最有效的方法是什么。
我喜欢这样的Mongodb模型
exports.getDownloads = function(processPD,processDW,responseMDW) {
DailyDowloadsModel.find({},function(err,foundData){
var select;
if (err) {
log.error(clientIP +" - DB Connection downloads failed - error");
res.status(500).send();
}
else {
if(foundData.length == 0){
var responseObject = null;
if(select && select == 'count'){
responseObject = {count: 0};
}
}else {
var responseObject = foundData;
if (select && select == "count") {
responseObject = {count: foundData.length};
}
processPD(processDW,responseObject,responseMDW);
}
}
});
}
示例文档
{
"_id" : ObjectId("5719ef37264f87331a3d0c54"),
"refunds" : "0",
"downloads" : "6",
"country" : "CA",
"date" : "2013-09-06",
"product_id" : "20600001319328",
"__v" : 0
}
我想计算总下载量。
答案 0 :(得分:2)
您有两种方法可以计算总数。
选项1: 聚合框架
与将所有文档发送到客户端并在那里进行数学运算相比,使用聚合框架执行此类操作要快得多。
注意:您的downloads
字段是字符串,它应该是一个数字。
db.collection.aggregate([
{$group:{_id:null, total:{$sum:"$downloads"}}}
])
在我的机器(Macbook Pro)上,它的总返回时间不到半秒。我在400000文档上运行测试。
选项2: map reduce
虽然强烈建议您更新文档结构以接受downloads
作为编号。但是,如果出于任何原因这不是一个选项,那么最好的选择是MongoDB提供的map reduce功能。
var map = function(){
emit(1, parseInt(this.downloads));
};
var reduce = function(key, values){
var reducedValue = Array.sum(values);
return reducedValue;
};
db.collection.mapReduce(map, reduce, {
out: { "inline" : 1}
});
map reduce比聚合框架慢,你可以看到,但比原始方法快得多。它将输出发送为:
{
"results" : [
{
"_id" : NumberInt(1),
"value" : NumberInt(2400000)
}
],
"timeMillis" : NumberInt(4112),
"counts" : {
"input" : NumberInt(400000),
"emit" : NumberInt(400000),
"reduce" : NumberInt(4000),
"output" : NumberInt(1)
},
"ok" : NumberInt(1)
}
您可以注意到,完成操作大约需要4秒钟。
答案 1 :(得分:0)
使用Mongo DB聚合
db.DailyDowloadsModel.aggregate([{$group:{_id:null, totalDownloads:{$sum:"$downloads"}}}]);
但是在此之前,请在Mongo DB中使用此命令在下载字段中进行索引。
db.DailyDowloadsModel.createIndex( { downloads: 1 });