0

我是 MongoDb 的新手,并且有一份(我想)MapReduce 或 Aggregation 的工作。

我有一个“发票”集合,其中包含以下格式的文档:

{
    date: 'some unix timestamp',
    total: 12345,
    paid: true
}

我需要在单元格中显示一个以月份(1 月至 12 月)为列的表格,每年的一行以及该月的总和(分为已付和未付)。像这样:

     |     Jan     |      Feb      | ...
2013 | 1,222 / 200 |  175 / 2,122  | ...
...

你能帮我得到正确的 mongo 命令吗?也许我最好写一些JS代码在mongo中执行?

4

2 回答 2

4

我现在找到了使用 MapReduce 的解决方案。这是 PHP 使用的:

$map = new MongoCode('
    function() {
        var d = new Date(this.date*1000);
        emit({y: d.getFullYear(), m: d.getMonth()}, {
            total: this.total,
            notPaid: this.paid ? 0 : this.total,
            count: 1
        });
    };
');

$reduce = new MongoCode('
    function(month, values) {
        result = { total: 0, notPaid: 0, count: 0 };
        for (var i = 0; i < values.length; i++) {
            result.total += values[i].total;
            result.notPaid += values[i].notPaid;
            result.count += values[i].count;
        }
        return result;
    };
');

$result = $db->command(array(
    'mapreduce' => 'invoices',
    'map' => $map,
    'reduce' => $reduce,
    'out' => 'temp'
));

echo $result['timeMillis'];

现在结果在“temp”集合中,每个月一个文档。可以优化或增强吗?

于 2013-01-08T20:35:42.377 回答
3

您可以使用这样的聚合框架来做到这一点:

db.invoices.aggregate( [
    {
        "$project" : {
            "yr" : {
                "$year" : "$date"
            },
            "mo" : {
                "$month" : "$date"
            },
            "total" : 1,
            "unpaid" : {
                "$cond" : [
                    "$paid",
                     0,
                    "$total"
                ]
            }
        }
    },
    {
        "$group" : {
            "_id" : {
                "y" : "$yr",
                "m" : "$mo"
            },
            "total" : {
                "$sum" : "$total"
            },
            "unpaid" : {
                "$sum" : "$unpaid"
            }
        }
    }
] )

您可以在最后使用 another$project来美化输出,并使用 a$sort对其进行排序,但这是它的基本功能核心。

于 2013-01-09T02:18:43.473 回答