【问题标题】:Mongodb aggregate sum embedded key pair objectsMongodb 聚合总和嵌入的密钥对对象
【发布时间】:2015-08-20 10:51:01
【问题描述】:

我有以下收藏

{

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

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

【问题讨论】:

  • 不太确定你在问什么。你想总结“每小时”中的所有值还是想要每个“每小时”总计从 0..23 开始?
  • 各个小时的总和值@Blakes
  • 我想你可能会这么说。无论如何,你现在有两种可能。

标签: mongodb mapreduce mongodb-query aggregation-framework


【解决方案1】:

您可能应该为此使用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 } }
)

或者如果你的意思是你只想要“每小时”的总数,那么这样做:

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": "$0",
            "1": "$1",
            "2": "$2",
            "3": "$3",
            "4": "$4",
            "5": "$5",
            "6": "$6"
        }
    }}
])

或者再次汇总“每小时”值,

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)来生成。

【讨论】:

  • 非常感谢朋友。顺便说一句,emit(null, obj); 这一行应该是emit(pos, obj),因为我想按位置分组
  • @Peramanathan 在这种情况下,我给出的示例会生成单个位置的总和,而不是每个“位置”的文档。如果这是您想要实现的目标,那当然是另一种方法。
猜你喜欢
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 2015-03-10
  • 2021-02-13
  • 2020-01-24
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
相关资源
最近更新 更多