我看你在你的问题的顶部初始查询,立刻告诉我,你的“时间戳“值实际上是字符串。所以毫无疑问,当你阅读这些信息并进行“手动聚合”时,实际上是在将这些值,可能还有其他值转换为可以操作,求和和求平均值的类型。
因此,这里的第一部分是修复您的数据,它看起来像来自日志记录源,但您从未转换过这些值。我正在考虑合理的可能性,这不仅仅是时间戳值,还可能是系统下的指标。
这使您可以选择如何存储时间戳。您可以将它保留为时间戳编号,因为它目前是字符串形式,或者您可以选择转换为。第一个将是一个简单的整数转换并保存,另一个应该能够提供给驱动程序支持的Date
类型,并再次保存数据。
完成此操作后,您就可以愉快地使用聚合功能。因此,作为一个例子,如果你选择保留这是一个数字,那么你只需要申请日期的功能,以获得组边界:
db.collection.aggregate([
// Match documents on the range you want
{ "$match": {
"timestamp": {
"$gte": 1396310400, "$lte": 1396915200
},
"service": "a715feac3db42f54edbc50ef6fa057b3"
}},
// Group on the time intervals, 15 minutes here
{ "$group": {
"_id": {
"service": "$service",
"time": {
"$subtract": [
"$timestamp",
{ "$mod": [ "$timestamp", 60 * 15 ] }
]
}
},
"load": { "$avg": "$system.load" }
}},
// Project to the output form you want
{ "$project": {
"service": "$_id.service",
"time" : "$_id.time",
"load": 1
}}
])
或者是PHP的具体
$tbl->aggregate(array(
array(
'$match' => array(
'timestamp' => array(
'$gte' => 1396310400, '$lte' => 1396915200
),
'service' => 'a715feac3db42f54edbc50ef6fa057b3'
)
),
array(
'$group' => array(
'_id' => array(
'service' => '$service',
'time' => array(
'$subtract' => array(
'$timestamp',
array('$mod' => array('$timestamp', 60 * 15))
)
)
),
'load' => array('$avg' => '$system.load')
)
),
array(
'$project' => array(
'service' => '$_id.service',
'time' => '$_id.time',
'load' => 1
)
)
))
否则,如果您选择转换为BSON日期,那么你可以使用date aggregation operators代替:
db.collection.aggregate([
{ "$match": {
"timestamp": {
"$gte": new Date("2014-04-01"), "$lte": new Date("2014-04-08")
},
"service": "a715feac3db42f54edbc50ef6fa057b3"
}},
{ "$group": {
"service": "$service",
"time": {
"dayOfYear": { "$dayOfYear": "$timestamp" },
"hour": { "$hour": "$timestamp" },
"minute": {
"$subtract": [
{ "$minute": "$timestamp" },
{
"$mod": [
{ "$minute": "$timestamp" },
15
]
}
]
}
},
"load": { "$avg": "$system.load" }
}},
{ "$project": {
"service": "$_id.service",
"time": "$_id.time",
"load": 1
}}
])
因此,有你有date aggregation operators的帮助下,打破了大的部分你有,并仍然使用相同的模运算,以获得区间值。
如果你还是喜欢日期的功能方法,你仍然可以使用日期对象从另一个减去一个日期对象将是划时代的时间戳值的结果做到这一点。因此,移动BSON日期为纪元时间戳仅仅是一个事:
{
"$subtract": [
"$dateObjectField",
new Date("1970-01-01")
]
}
你传递给管道因此,任何“日期”的价值观在这里你可以施放使用驱动程序的原生类型的方法,这将是当请求发送到MongoDB时序列化正确。另一个优点是,当你阅读它们时也是如此,所以在客户端处理中不再需要转换。
尼尔您好,感谢的全面的答案。我会在接下来的20分钟左右执行此操作,并会报告回来。 我期待改变时间戳字段到BSON原生格式,我只是还没有想通做到这一点还没有最好的方式。 –
您的答案完美无缺,我只需要纠正':' ' array('$ mod':array('$ timestamp',60 * 15))' 现在,数据存储在MySQL所以我的测试数据,我写道,在从MySQL时选择数据的批次,并插入行到MongoDB中的脚本。这可能是出于这个问题的范围,但有什么具体的我需要做的,我现在的时间戳格式(UNIX时间戳)转换为蒙戈的可用的格式? –
@LeeBrooks有关于MongoDB驱动程序的文档,包括[MongoDate](http://www.php.net//manual/en/class.mongodate.php)class –