MongoDB-在一个查询中聚合多个字段

MongoDB-在一个查询中聚合多个字段,mongodb,Mongodb,我正在为我们公司的生产系统开发一个监控系统。这意味着我将要存储的数据的性质是时间序列。在查看了其他几个数据库之后,我选择了MongoDB。 生产系统中的事件将一直到达,但我打算将事件存储在一个10分钟间隔的文档中。最终,集合中的文档将如下所示: { _id: '04/25/2015 13:00', event1_count : 130, event2_count : 50, event3_count : 200 }, { _id: '04/25/2015 13:

我正在为我们公司的生产系统开发一个监控系统。这意味着我将要存储的数据的性质是时间序列。在查看了其他几个数据库之后,我选择了MongoDB。 生产系统中的事件将一直到达,但我打算将事件存储在一个10分钟间隔的文档中。最终,集合中的文档将如下所示:

{
   _id: '04/25/2015 13:00',
   event1_count : 130,
   event2_count : 50,
   event3_count : 200
},

{
    _id: '04/25/2015 13:10',
    event1_count : 230,
    event2_count : 20,
    event3_count : 400
}
文档
\u id:'04/25/2015 13:00'
简单地说,它包含了所有在04/25/2015 13:00和04/25/2015 13:10之间到达的事件

最终,我希望在数据上运行不同的报告。例如-过去20分钟内的事件计数。 在过去20分钟内,我希望得到的事件计数结果是:

{
event1_count : 360,
event2_count : 70,
event3_count : 600
}
我的问题-有没有一种方法可以在一个查询中聚合来自不同文档的多个字段


顺便说一句,对我来说,将数据保持在10分钟的间隔是很重要的,因为其他报告需要这种时间分辨率。

是的,这确实是可能的。假设您的集合将在上述结构中存储文档,您可以通过添加另一个字段(如
date
)来修改该结构,该字段将_id存储为ISODate,而不是字符串时间戳,以便您可以使用进行聚合。要进行转换,可以使用mongo的游标方法对运算符进行原子更新:

db.collection.find().forEach(function (doc){
    var dateObject = new Date(doc._id);    
    db.collection.update({_id: doc._id}, { $set: { date: dateObject } });               
});
上述操作将在文档中创建一个额外字段
date
,该字段包含
\u id
字符串的ISODate对象表示形式

假设在上述更新之后,您的集合中现在有以下示例文档:

/* 0 */
{
    "_id" : "04/25/2015 13:00",
    "event1_count" : 130,
    "event2_count" : 50,
    "event3_count" : 200,
    "date" : ISODate("2015-04-25T13:00:00.000Z")
}

/* 1 */
{
    "_id" : "04/25/2015 13:10",
    "event1_count" : 230,
    "event2_count" : 20,
    "event3_count" : 400,
    "date" : ISODate("2015-04-25T13:10:00.000Z")
}

/* 2 */
{
    "_id" : "04/25/2015 13:20",
    "event1_count" : 240,
    "event2_count" : 30,
    "event3_count" : 350,
    "date" : ISODate("2015-04-25T13:20:00.000Z")
}

/* 3 */
{
    "_id" : "04/25/2015 13:30",
    "event1_count" : 180,
    "event2_count" : 60,
    "event3_count" : 500,
    "date" : ISODate("2015-04-25T13:30:00.000Z")
}
以下聚合管道将根据20分钟的间隔为您提供所需的结果:

var interval = 20,
    pipeline = [
    { 
        "$group": {
            "_id": {
                "year": { "$year": "$date" },
                "dayOfYear": { "$dayOfYear": "$date" },
                "interval": {
                    "$subtract": [ 
                        { "$minute": "$date" },
                        { "$mod": [{ "$minute": "$date" }, interval ] }
                    ]
                }
            },
            "event1_count": { "$sum": "$event1_count" },
            "event2_count": { "$sum": "$event2_count" },
            "event3_count": { "$sum": "$event3_count" }
        }
    },
    {
        "$project": {
            "_id": 0,
            "event1_count": 1,
            "event2_count": 1,
            "event3_count": 1
        }
    }
];

db.collection.aggregate(pipeline);
输出

/* 0 */
{
    "result" : [ 
        {
            "event1_count" : 420,
            "event2_count" : 90,
            "event3_count" : 850
        }, 
        {
            "event1_count" : 360,
            "event2_count" : 70,
            "event3_count" : 600
        }
    ],
    "ok" : 1
}

在我的问题中,您可以看到2个文档。每个文档都有几个字段-event1\u count、event2\u count等。我想对两个文档中的event\u count1求和,event\u count2也是如此。所以结果应该是事件计数1的和,事件计数2的和,依此类推。我在一个查询中寻找实现这一点的方法,假设我还有很多其他事件,而不是像我的示例中那样只有3个。@assafm不用担心:-)