使用mapReduce在mongodb中检索总和以及计数

Vib*_*has 0 javascript mapreduce mongodb 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
Run Code Online (Sandbox Code Playgroud)

我试过了

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();
Run Code Online (Sandbox Code Playgroud)

这给了我结果而不是计数。

Nei*_*unn 5

因此,在这种情况下,您可能真的想要聚合框架。它以本机代码操作运行,并且比的JavaScript评估所能达到的速度快得多mapReduce

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 }
)
Run Code Online (Sandbox Code Playgroud)

它效率更高而且编码非常简单。

另请查看SQL到聚合的映射表以获取常见示例。

如果确实需要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")
            }
       }
   }
)
Run Code Online (Sandbox Code Playgroud)

但是,在没有限制结果收集的情况下,使用聚合管道时,就不会像使用“限制”结果那样得到相同的结果。

  • @Vibhas这就是为什么您将`allowDiskUse`用作参数的原因 (2认同)