我在MongoDB中有这些数据:
{
"_id": ObjectId("542bxxxxxxxxxxxx"),
"TEMP_C": 13,
"time": ISODate("2014-08-21T05:30:00Z")
}
我希望白天将其分组并将其提供给Highcharts,以显示每天的平均温度 . 像这样:http://jsfiddle.net/tw7n6wxb/3/
使用MongoDB Aggregation Pipeline,我能够根据其他一些示例和这篇伟大的帖子进行分组:http://www.kamsky.org/stupid-tricks-with-mongodb/stupid-date-tricks-with-aggregation-framework
附带问题:为什么在MongoDB中按日期分组这么复杂?最烦人的部分是在将日期对象分成'$ dayOfMonth','$ month'和'$ year'之后重新组合日期对象 . 有没有更简单的方法呢?
无论如何,我让这部分工作(我想) . 这是结果:
{
"_id" : {"sec":1409346800,"usec":0},
"avg" : 12
},
{
"_id" : {"sec":1409356800,"usec":0},
"avg" : 15
},
但是,Highcharts系列将值对的数组作为输入:示例:data:[[5,2],[6,3],[8,2]] . 每对上的第一个值是X值,该值必须是一个数字(当X轴配置为datetime时,X值以毫秒为单位) .
我遇到的问题是MongoDB将日期作为MongoDate对象返回,其中包含两个值,'sec'和'usec',而Highcharts期待一个数字 .
无论如何将MongoDate对象转换为管道中的整数?以$项目为例?我正在使用PHP,但我想避免在应用程序中进行后处理(如PHP日期格式化) .
或者,关于如何解决这个问题的任何其他想法?
谢谢,
1 回答
您似乎只想要从结果返回的时间戳值 . 确实有一种简单的方法可以在聚合框架中执行此操作而不使用date aggregation operators . 您可以使用基本的"date math",并使用可用于从日期对象中提取"timestamp"值并操纵它的技巧:
因此,基本的“技巧”是,当从另一个(或类似操作)中减去一个日期对象时,返回的结果是两个时间差的“毫秒”数 . 因此,通过使用“1970-01-01”的“纪元”日期,您可以将日期对象的“纪元时间戳”值作为数字 .
然后通过从一天中的毫秒中减去模数(或余数)来应用基本日期数学 . 这会“舍入”该值以表示记录条目的“日期” .
我喜欢发布JSON,因为它解析了所有地方,但是以更加PHP的方式,然后像这样:
所以这比使用日期聚合运算符更清晰,以达到预期的结果 . 当然,对于您希望如何在客户端中使用数据的方式呈现数据,这仍然不是“全程” .
这里真正要处理的是操作结果,以便获得所需的输出格式 . 在返回响应之前,这可能更适合于执行操作的服务器代码,但如果您使用MongoDB 2.6或更高版本,则可以在聚合管道本身内执行此操作:
所以这真的很狡猾 . 完成初始"grouping"以确定每天的平均值后,您每天在结果文档中获得两个字段
_id
和avg
. $map运算符在这里做的是将数组作为输入(在这种情况下,只是一个带有一对值的编号模板来标识位置)并处理每个元素以返回一个等于原始元素的数组 .这里的$cond运算符允许您查看该数组的当前元素的值,并使用当前文档中存在的另一个值来查看"swap it" . 因此,对于每个文档,结果包含一些配对数组,如:
然后发生的一切都是将所有结果推送到一个文档中,其中“data”数组如下所示:
现在,您在该结果中的数据元素是一个表示所需点的数组对数组 .
当然,像
$map
这样的运营商只能从MongoDB 2.6及以后版本获得,所以如果你有可用的那么你可以使用它们,但是只需用类似的"map"操作处理代码中的结果:因此,无论您采用哪种方式,这都归结为数组操作,但日期操作技巧也可以为您节省一些工作,以获得结果作为预期的时间戳值 .