MongoDB Map减少在高数据量中返回意外结果

时间:2014-07-12 17:33:39

标签: php mongodb mapreduce aggregation-framework

我是PHP和mongo DB的新手 我有一个80000条记录的数据集,这是一个本地部署。

我的数据结构很简单:

(
    [_id] => MongoId Object
        (
            [$id] => 53c146aebc7d867d058b94b3
        )

    [name] => Mark
    [txnType] => Borrowed
    [amount] => 5876
)

我正在运行Map Reduce Job,定义如下:

$map = new MongoCode("function ()
{
    { 
        emit({name:this.name,type:this.txnType},this.amount);
    }
}");
$reduce = new MongoCode("
    function (key, values)
    {
        var total=0;
        var count=0;
        for (var i in values) { 
            if (!isNaN(values[i])) {
                total+=values[i];
            };
            count++;
        }
        return {total:total, count:count};
    }
    ");

$sales =  $db->command(array(
    "mapreduce" => "data", 
    "map" => $map,
    "reduce" => $reduce,
    "out" => "sales"
    ));

概念基本上是有4个人可能有Borrowed,Sold,Purchase和Lent类型的交易。每条记录代表一个txn。

我想创建一个数据透视图来获取数据:

  

名称:类型:总金额:Txns计数

一些支持的数据如何搞砸了。加起来的计数应该加起来为80000,但是它的加起来只有216。

我无法理解为什么会这样。 谁能帮帮我吗。我哪里出错了,纠正什么。

我的需要是基本上为交易制定分析。

1 个答案:

答案 0 :(得分:1)

问题是您的emit输出的格式与reduce相同。

这是你为价值所发出的:

this.amount

以下是您从reduce返回的内容:

return {total:total, count:count};

为了使reduce在重新减少时正常工作(请记住,reduce可以在同一个键值上调用为零,一次或多次),您必须发出以下格式:

emit({name:this.name,type:this.txnType},{ total: this.amount, count: 1} );

因此你的reduce函数现在应该是:

    var total=0;
    var count=0;
    for (var i in values) { 
        if (!isNaN(values.total[i])) {
            total+=values.total[i];
        };
        count+=values.count;
    }
    return {total:total, count:count};

The two most important rules of mapReduce in MongoDB

  1. 以与reduce函数返回完全相同的格式发出值

  2. 结构减少,以便每个键可以被称为零,一次或多次

  3. 请注意,您可以使用聚合框架更高效,更快地执行相同的聚合,如下所示:

    db.collection.aggregate( {$group: 
        { _id : {name: "$name", type: "$txnType"},
          total: {$sum: "$amount"},
          count: {$sum: 1}
        }
    }