使用mapReduce检索总和以及mongodb中的count

时间:2015-02-28 12:11:35

标签: javascript mongodb mapreduce mongodb-query aggregation-framework

如何使用mapReduce将以下SQL查询转换为mongoDB

SELECT mobile, SUM( amount ),count(mobile) as noOfTimesRecharges
FROM recharge
WHERE recharge_date  between  '2015-02-26' AND  '2015-03-27'
GROUP BY mobile
having noOfTimesRecharges > 0 and  noOfTimesRecharges < 5

我试过了

db.users.mapReduce(
function(){
emit(this.mobile,this.amount);
},
function(k,v){
return Array.sum(v)
},
{
query:{
recharge_date:{$gte:ISODate("2014-06-17"),$lte:ISODate("2014-06-20")}
},
out:"one_month_data" 
}).find();

给了我结果但不给了计数。

1 个答案:

答案 0 :(得分:5)

所以你可能真的想要aggregation framework。它在本机代码操作中运行,比从mapReduce的JavaScript评估中获得的速度快得多。

db.users.aggregate([
    { "$match": {
        "recharge_date": {
            "$gte": ISODate("2014-06-17"),
            "$lte": ISODate("2014-06-20")
        }
    }},
    { "$group": {
        "_id": "$mobile",
        "amount": { "$sum": "$amount" },
        "count": { "$sum": 1 }
    }},
    { "$match": {
        "count": { "$gt": 1, "lt": 5 }
    }}
    { "$out": "newCollection" }
],
{ "allowDiskUse": true }
)

编码效率更高,更简单。

另请查看SQL to agregation mapping chart以获取常见示例。

如果你确实需要mapReduce(你可能不需要),那么正确的方法是:

db.users.mapReduce(
    function() { 
        emit( this.mobile, { "amount": this.amount, "count": 1 } );
    },
    function(key,values) {
        var doc = { "amount": 0, "count": 0 };
        values.forEach(function(value) {
            doc.amount += value.amount;
            doc.count += value.count;
        };
        return doc;
   },
   { 
       "out": { "replace": "newCollection" },
       "query": {
           "recharge_date": {
               "$gte": ISODate("2014-06-17"),
               "$lte": ISODate("2014-06-20")
            }
       }
   }
)

但是,对于“限制”结果,您没有像使用聚合管道那样得到相同的情况,而无需对结果集合进行额外处理。