我正在尝试基于文档中的日期字段以"YYYYMMDD“的形式创建聚合键。但是,使用$month
和$dayOfMonth
运算符,我只返回数字,没有将它们格式化为前导零的方法(此外,我无法连接数字)。
我更喜欢聚合而不是Map/Reduce,因为后者具有阻塞特性。有什么想法吗?
发布于 2014-08-04 09:14:29
基本上,您可以使用$concat运算符以几个条件连接字符串,并使用$substr来处理转换:
"day": {
"$concat": [
{ "$substr": [ { "$year": "$date" }, 0, 4 ] },
{ "$cond": [
{ "$lte": [ { "$month": "$date" }, 9 ] },
{ "$concat": [
"0", { "$substr": [ { "$month": "$date" }, 0, 2 ] }
]},
{ "$substr": [ { "$month": "$date" }, 0, 2 ] }
]},
{ "$cond": [
{ "$lte": [ { "$dayOfMonth": "$date" }, 9 ] },
{ "$concat": [
"0", { "$substr": [ { "$dayOfMonth": "$date" }, 0, 2 ] }
]},
{ "$substr": [ { "$dayOfMonth": "$date" }, 0, 2 ] }
]}
]
}
如果要按“日期”进行聚合,则另一种方法是在日期数学中使用“划时代”值:
"day": {
"$subtract": [
{ "$subtract": [ "$date", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$date", new Date("1970-01-01") ] },
1000 * 60 * 60 * 24
]}
]
}
两个日期对象上的任何日期数学操作都会导致时间毫秒的差异。因此,使用划时代日期作为日期对象,以便进行转换。结果值是时间戳值的"day“,在处理结果时可以反馈以创建date对象。
可以说,您可以在对$year和$dayOfYear结果进行后处理时执行相同的操作,因为这些结果也足以在客户端处理中重新构成日期对象。
发布于 2015-08-03 09:57:08
虽然尼尔的答案是有效的,但我觉得它相当令人不满意;它很难读懂,很难保持,而且速度慢。假设您从一个日期中获得了值(如OP中提到的那样);如果您使用的是mongo3.0或更高版本,那么使用$dateToString是最好的方法,但是如果您停留在更早的版本(像我一样),我认为最好只是从date字段读取您想要的字符串的部分(因为这些都是零填充的):
formattedTime: {
$concat: [
{ $substr: ["$timestamp", 0, 4] },
{ $substr: ["$timestamp", 5, 2] },
{ $substr: ["$timestamp", 8, 2] }
]
}
这在我只想得到<hours>:<minutes>
的情况下特别有效(使用@Neil的解决方案是一种正确的痛苦,因为我想将两个数字为零),但是这种方式变得简单了:formattedTime: { $substr: [ "$timestamp", 11, 5 ] }
当然,为了提高可读性,我建议用一些命名的常量替换神奇的数字。
https://stackoverflow.com/questions/25114870
复制相似问题