如何加速Mongo DB中的数据读取速度

时间:2016-04-22 12:36:15

标签: mongodb mongoose

我的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
}

我想计算总下载量。

2 个答案:

答案 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 });