Mongodb 聚合总和嵌入密钥对对象

Mongodb aggregate sum embedded key pair objects

我有以下合集

{

  "pos": 1
  "daily": 1,
  "hourly": {
    "15": 1,
    "23": 4
  }
}

每小时的范围从 0 到 23,我只想按位置分组,并希望聚合 ($sum) 每日和个人小时数。每小时有点欺骗我。

您可能应该为此使用 mapReduce,聚合框架无法遍历对象的键:

db.collection.mapReduce(
    function() {
        var obj = { "daily": this.daily, "hourly": {} };
        for ( var x=0; x <= 23; x++ ) {
            obj.hourly[x] = 0;
        }

        var hourly = this.hourly;
        Object.keys(hourly).forEach(function(hour) {
            obj.hourly[hour] += hourly[hour];
        });
        emit(null, obj);
    },
    function(key,values) {
        var obj = { "daily": 0, "hourly": {} };
        for ( var x=0; x <= 23; x++ ) {
            obj.hourly[x] = 0;
        }

        values.forEach(function(value) {
            obj.daily += value.daily;
            Object.keys(value.hourly).forEach(function(hour) {
                obj.hourly[hour] += value.hourly[hour];
            });
        });
        return obj;
    },
    { "out": { "inline": 1 } }
)

或者如果你的意思是你只想要 "hourly" 的总数,那么这样做:

db.collection.mapReduce(
    function() {
        var obj = { "daily": this.daily, "hourly": 0 };

        var hourly = this.hourly;
        hourly.forEach(function(hour) {
            obj.hourly+= hourly[hour];
        });
        emit(null, obj);
    },
    function(key,values) {
        var obj = { "daily": 0, "hourly": 0 };
        values.forEach(function(value) {
            obj.daily += value.daily;
            obj.hourly += value.hourly;
        });
        return obj;
    },
    { "out": { "inline": 1 } }
)

使用聚合框架执行此操作看起来非常糟糕。在这里缩短时间,但你应该看到基本要求是什么:

db.collection.aggregate([
    { "$group": {
        "_id": null,
        "daily": { "$sum": "$daily" },
        "0": { "$sum": "$hourly.0" },
        "1": { "$sum": "$hourly.1" }, 
        "2": { "$sum": "$hourly.2" },
        "3": { "$sum": "$hourly.3" },
        "4": { "$sum": "$hourly.4" },
        "5": { "$sum": "$hourly.5" },
        "6": { "$sum": "$hourly.6" }
    }},
    { "$project": {
        "daily": 1,
        "hourly": {
            "0": "[=12=]",
            "1": "",
            "2": "",
            "3": "",
            "4": "",
            "5": "",
            "6": ""
        }
    }}
])

或者再次计算 "hourly" 个值的总和,

db.collection.aggregate([
    { "$group": {
        "_id": null,
        "daily": { "$sum": "$daily" },
        "hourly": { 
            "$sum": { "$add": [
                "$hourly.0",,
                "$hourly.1",
                "$hourly.2",
                "$hourly.3",
                "$hourly.4",
                "$hourly.5",
                "$hourly.6"
            ]}
        }
    }}
])

您当然可以使用代码生成聚合管道阶段,因为它们只是数据结构。因此,可以使用 mapReduce 示例(循环 0..23)中所示的类似方法来生成。