MondoDB 聚合 - 每天的绝对计数



我有以下(已聚合的)集合

{ "_id" : { "day" : "2015-02-01" }, "total" : 2 }
{ "_id" : { "day" : "2015-02-02" }, "total" : 3 }
{ "_id" : { "day" : "2015-02-03" }, "total" : 10 }
{ "_id" : { "day" : "2015-02-04" }, "total" : 10 }
{ "_id" : { "day" : "2015-02-05" }, "total" : 5 }

我需要的是计算每天的绝对值,将前几天相加。所以预期的结果将在上述情况下

{ "_id" : { "day" : "2015-02-01" }, "absolutetotalforday" : 2 }
{ "_id" : { "day" : "2015-02-02" }, "absolutetotalforday" : 5 }
{ "_id" : { "day" : "2015-02-03" }, "absolutetotalforday" : 15 }
{ "_id" : { "day" : "2015-02-04" }, "absolutetotalforday" : 25 }
{ "_id" : { "day" : "2015-02-05" }, "absolutetotalforday" : 30 }

目前不知道如何使用 1 个查询实现此目的。当然,我可以为我感兴趣的每一天做一笔钱,但这可能是一个很长的时间范围

任何帮助表示赞赏

由于聚合框架没有知道前一个文档的值或文档的先前"分组"值的机制,因此在这种情况下,最好的选择是使用 Map-Reduce

Map-Reduce将在您需要的一天结束时为您提供当前总计的"运行总计",尽管这不会在所需的键中,absolutetotalforday而是在一个名为value的键中,因为减少的值始终在value键中。

以下mapReduce()操作将为您提供所需的结果,假设上一个聚合操作的结果已输出到名为 agg_results 的单独集合:

db.agg_results.mapReduce(
    function() { emit( this._id, this.total ); },  
    function(key, values) { return Array.sum(values); },
    { 
        "scope": { "total": 0 },
        "finalize": function(key, value) {
            total += value;
            return total;
        },
        "out": { "inline": 1 }
    }
); 

示例输出

{
    "results" : [ 
        {
            "_id" : {
                "day" : "2015-02-01"
            },
            "value" : 2
        }, 
        {
            "_id" : {
                "day" : "2015-02-02"
            },
            "value" : 5
        }, 
        {
            "_id" : {
                "day" : "2015-02-03"
            },
            "value" : 15
        }, 
        {
            "_id" : {
                "day" : "2015-02-04"
            },
            "value" : 25
        }, 
        {
            "_id" : {
                "day" : "2015-02-05"
            },
            "value" : 30
        }
    ],
    "timeMillis" : 0,
    "counts" : {
        "input" : 5,
        "emit" : 5,
        "reduce" : 0,
        "output" : 5
    },
    "ok" : 1
}

对结果进行排序不适用于内联结果和字符串类型的日期。相反,请尝试将日期字符串转换为 JavaScript date 对象,将结果写入集合,然后对该集合运行排序:

db.agg_results.mapReduce(
    function() { emit( new Date(this._id.day), this.total ); },  
    function(key, values) { return Array.sum(values); },
    { 
        "scope": { "total": 0 },
        "finalize": function(key, value) {
            total += value;
            return total;
        },
        "out": "tmpResults"
    }
); 

示例输出(带排序)

> db.tmpResults.find().sort({_id: 1})
{ "_id" : ISODate("2015-02-01T00:00:00Z"), "value" : 2 }
{ "_id" : ISODate("2015-02-02T00:00:00Z"), "value" : 5 }
{ "_id" : ISODate("2015-02-03T00:00:00Z"), "value" : 15 }
{ "_id" : ISODate("2015-02-04T00:00:00Z"), "value" : 25 }
{ "_id" : ISODate("2015-02-05T00:00:00Z"), "value" : 30 }
>

相关内容

  • 没有找到相关文章

最新更新