是否有可能进行此类计算并使用MongoDB返回此结果?

时间:2016-11-12 10:23:40

标签: javascript mongodb mongodb-query

我是MongoDB的新手。考虑以下集合:

{
"_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
"date" : ISODate("2016-11-12T00:00:00.000Z"),
"statistics" : {
    "members" : {
        "topPerformers" : {
            "hours" : [ 
                {
                    "workHour" : 10,
                    "Darth Vader" : 72,
                    "Walrus Man" : 80,
                    "Imperial Stromtrooper" : 60
                }, 
                {
                    "workHour" : 11,
                    "Darth Vader" : 142,
                    "Walrus Man" : 115,
                    "Imperial Stromtrooper" : 100
                }, 
                {
                    "workHour" : 12,
                    "Darth Vader" : 116,
                    "Walrus Man" : 81,
                    "Imperial Stromtrooper" : 113
                }, 
                {
                    "workHour" : 13,
                    "Darth Vader" : 128,
                    "Walrus Man" : 90,
                    "Imperial Stromtrooper" : 141
                }, 
                {
                    "workHour" : 14,
                    "Darth Vader" : 95,
                    "Walrus Man" : 118,
                    "Imperial Stromtrooper" : 116
                }, 
                {
                    "workHour" : 15,
                    "Darth Vader" : 91,
                    "Walrus Man" : 93,
                    "Imperial Stromtrooper" : 124
                }, 
                {
                    "workHour" : 16,
                    "Darth Vader" : 144,
                    "Walrus Man" : 95,
                    "Imperial Stromtrooper" : 111
                }, 
                {
                    "workHour" : 17,
                    "Darth Vader" : 143,
                    "Walrus Man" : 72,
                    "Imperial Stromtrooper" : 136
                }, 
                {
                    "workHour" : 18,
                    "Darth Vader" : 54,
                    "Walrus Man" : 88,
                    "Imperial Stromtrooper" : 87
                }, 
                {
                    "workHour" : 19,
                    "Darth Vader" : 82,
                    "Walrus Man" : 146,
                    "Imperial Stromtrooper" : 67
                }, 
                {
                    "workHour" : 20,
                    "Darth Vader" : 88,
                    "Walrus Man" : 136,
                    "Imperial Stromtrooper" : 52
                }, 
                {
                    "workHour" : 21,
                    "Darth Vader" : 92,
                    "Walrus Man" : 113,
                    "Imperial Stromtrooper" : 124
                }, 
                {
                    "workHour" : 22,
                    "Darth Vader" : 91,
                    "Walrus Man" : 68,
                    "Imperial Stromtrooper" : 128
                }, 
                {
                    "workHour" : 23,
                    "Darth Vader" : 125,
                    "Walrus Man" : 64,
                    "Imperial Stromtrooper" : 84
                }, 
                {
                    "workHour" : 0,
                    "Darth Vader" : 97,
                    "Walrus Man" : 108,
                    "Imperial Stromtrooper" : 75
                }
            ]
        }
    }
}
}

每天1天的记录都是这样的,例如我每天在集合中有30个文件。我可以使用我想要的日期范围db.getCollection('name').find({ date: { $gte: new ISODate(), $lt: new ISODate() } }),然后如果我选择整个月的记录,我可以循环statistics.members.topPerformers.hours并计算当天每个成员的总数客户端使用Javascript,如:

statistics.members.topPerformers.hours.forEach((hour) => {
          Object
            .keys(hour)
            .filter(key => key !== 'workHour')
            .forEach((key) => {
              result[key] = (result[key] || 0) + hour[key];
            });
        });

我可以使用Mongo在服务器端执行并返回修改后的结果,例如:

{
"_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
"date" : ISODate("2016-11-12T00:00:00.000Z"),
"statistics" : {
    "members" : {
        "topPerformers" : {
            "hours" : [ 
                {
                    "workHour" : 10,
                    "Darth Vader" : 2512,
                    "Walrus Man" : 1423,
                    "Imperial Stromtrooper" : 1487
                }, 
             ]
          }
       }
    }

1 个答案:

答案 0 :(得分:0)

您可以运行一个聚合管道,该管道利用 $match 运算符管道阶段按给定的日期范围过滤集合中的文档,前面的 {{3} } 运算符展平嵌入的小时数组,然后您可以使用 $unwind 管道对非规范化文档进行分组并计算总和。

以下mongo shell操作演示了以上内容:

var start = new Date();
start.setHours(0,0,0,0);

var end = new Date();
end.setHours(23,59,59,999);

db.collection.aggregate([
    { "$match": { "date": { "$gte": start, "$lte": end } } },
    { "$unwind": "$statistics.members.topPerformers.hours" },
    {
        "$group": {
            "_id": "$_id",
            "date": { "$first": "$date" },
            "workHour" : { 
                "$sum": "$statistics.members.topPerformers.hours.workHour" 
            },
            "Darth Vader" : { 
                "$sum": "$statistics.members.topPerformers.hours.Darth Vader" 
            },
            "Walrus Man" : { 
                "$sum": "$statistics.members.topPerformers.hours.Walrus Man" 
            },
            "Imperial Stromtrooper" : { 
                "$sum": "$statistics.members.topPerformers.hours.Imperial Stromtrooper" 
            }
        }
    }
]);

示例输出

{
    "_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
    "date" : ISODate("2016-11-12T00:00:00.000Z"),
    "workHour" : 231.0,
    "Darth Vader" : 1560.0,
    "Walrus Man" : 1467.0,
    "Imperial Stromtrooper" : 1518.0
}

虽然没有必要,但您可以通过附加 $group 管道来重塑最终文档字段

db.collection.aggregate([
    { "$match": { "date": { "$gte": start, "$lte": end } } },
    { "$unwind": "$statistics.members.topPerformers.hours" },
    {
        "$group": {
            "_id": "$_id",
            "date": { "$first": "$date" },
            "workHour" : { 
                "$sum": "$statistics.members.topPerformers.hours.workHour" 
            },
            "Darth Vader" : { 
                "$sum": "$statistics.members.topPerformers.hours.Darth Vader" 
            },
            "Walrus Man" : { 
                "$sum": "$statistics.members.topPerformers.hours.Walrus Man" 
            },
            "Imperial Stromtrooper" : { 
                "$sum": "$statistics.members.topPerformers.hours.Imperial Stromtrooper" 
            }
        }
    },
    {
        "$project": {
            "date": 1,
            "statistics.members.topPerformers.hours.workHour": "$workHour",,
            "statistics.members.topPerformers.hours.Darth Vader": "$Darth Vader",
            "statistics.members.topPerformers.hours.Walrus Man": "$Walrus Man",
            "statistics.members.topPerformers.hours.Imperial Stromtrooper": "$Imperial Stromtrooper"
        }
    }
])

<强>输出

{
    "_id" : ObjectId("c0c672fa6db9b3f954732b1a"),
    "date" : ISODate("2016-11-12T00:00:00.000Z"),
    "statistics" : {
        "members" : {
            "topPerformers" : {
                "hours" : {
                    "workHour" : 231.0,
                    "Darth Vader" : 1560.0,
                    "Walrus Man" : 1467.0,
                    "Imperial Stromtrooper" : 1518.0
                }
            }
        }
    }
}