聚合框架- mongodb以10分钟的间隔聚合时间戳



我试图将匹配查询的大型数据集分组为10分钟的"时间片"。我想知道是否有任何方法可以有效地使用mongodb的聚合函数。

我有一个文档,看起来像:

{
    _id: ObjectID(""),
    groupID: '1234',
    name: 'dataPointName',
    timestamp: 1432765200000,
    value: 1234
}

然后,我想在称为"grouped_data"的10分钟组间隔内对[timestamp,value]对数组进行分组。我想知道是否有一种有效的方法来执行所有这些操作?

您可以从投影一个新的日期字段开始,然后您可以根据间隔对其进行分组。

假设您有以下测试文档:

db.collection.insert([
    {
        groupID: '1234',
        name: 'dataPointName',
        timestamp: 1432765200000,
        value: 1234
    },
    {
        groupID: '1234',
        name: 'dataPointName',
        timestamp: 1432765300000,
        value: 1234
    },
    {
        groupID: '1234',
        name: 'dataPointName',
        timestamp: 1432766100000,
        value: 1234
    }
])

然后可以实现以下聚合:

db.collection.aggregate([
    {
        "$project": {
            "date": { "$add": [new Date(0), "$timestamp"] },
            "timestamp": 1,
            "value": 1
        }
    },
    { 
        "$group": {
            "_id": {
                "year": { "$year": "$date" },
                "dayOfYear": { "$dayOfYear": "$date" },
                "interval": {
                    "$subtract": [ 
                        { "$minute": "$date" },
                        { "$mod": [{ "$minute": "$date"}, 10 ] }
                    ]
                }
            },
            "grouped_data": { "$push": {"timestamp": "$timestamp", "value": "$value" } }
        }
    },
    {
        "$project":{
            "_id": 0,
            "grouped_data": 1
        }
    }
])

:

/* 0 */
{
    "result" : [ 
        {
            "grouped_data" : [ 
                {
                    "timestamp" : 1432766100000,
                    "value" : 1234
                }
            ]
        }, 
        {
            "grouped_data" : [ 
                {
                    "timestamp" : 1432765200000,
                    "value" : 1234
                }, 
                {
                    "timestamp" : 1432765300000,
                    "value" : 1234
                }
            ]
        }
    ],
    "ok" : 1
}

EDIT

要将数据格式化为像[timestamp,value]这样的数组,而不是键/值数组,您可以使用聚合游标的forEach()方法,如下所示:

var result = [];   
db.collection.aggregate(pipeline).forEach(function (doc){    
    data = []; 
    doc.grouped_data.forEach(function (obj){               
        data.push(obj.timestamp);
        data.push(obj.value);        
    });
    result.push(data);
})
printjson(result);

[
        [
                1432766100000,
                1234
        ],
        [
                1432765200000,
                1234,
                1432765300000,
                1234
        ]
]

这显然是一个可以使用map-reduce轻松解决的问题。这里的键是timestamp / (10*60*1000),四舍五入到最小的整数。您只需要在reduce步骤中聚合grouped_data

然而,这有点复杂,因为我假设您需要按时间戳排序您的值(记住reduce函数应该是可交换的)。为了提供帮助,我将使用终结器对结果进行排序。

map = function() {
  window_width = 10*60*1000
  emit(Math.floor(this.timestamp/window_width),
       { grouped_data: [[ this.timestamp, this.value]] })
}
// aggregates values by concatenating the [[timestamp, values]] arrays
// don't bother sorting here as this will be done by the finalizer
reduce = function(key, values) {
  return values.reduce(
            function(a,b) { return { grouped_data: a.grouped_data.concat(b.grouped_data)} }
      )
} 
// Sort data in each array by timestamp
finalize = function(key, reducedValue) {
  return { grouped_data: reducedValue.grouped_data.sort(function(a,b) { a[0] - b[0] }) }
}

生产(使用一些虚拟数据集):

> db.w.mapReduce(map, reduce, { finalize: finalize, out: {inline:1}}).results
[
    {
        "_id" : 2387925,
        "value" : {
            "grouped_data" : [
                [
                    1432755300001,
                    1234
                ],
                [
                    1432755300000,
                    1234
                ]
            ]
        }
    },
    {
        "_id" : 2387942,
        "value" : {
            "grouped_data" : [
                [
                    1432765200000,
                    1234
                ],
                [
                    1432765200001,
                    1234
                ],
                [
                    1432765300000,
                    1234
                ],
                [
                    1432765300001,
                    1234
                ]
            ]
        }
    }
]

最新更新