我正在尝试以" YYYYMMDD"的形式创建聚合键。基于我的文档中的日期字段。但是,使用$month
和$dayOfMonth
运算符,我只会返回数字,而无法将它们格式化为前导零(此外,我无法连接数字)。
由于后者的阻塞性,我更喜欢聚合Map / Reduce。有什么想法吗?
答案 0 :(得分:9)
您基本上使用$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"进行汇总。就是用一个"时代"使用日期数学的值:
"day": {
"$subtract": [
{ "$subtract": [ "$date", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$date", new Date("1970-01-01") ] },
1000 * 60 * 60 * 24
]}
]
}
对两个日期对象的任何日期数学运算都会导致epoch毫秒作为差异。因此,使用纪元日期作为日期对象进行转换。结果值是" day"对于时间戳值,可以在处理结果时反馈以创建日期对象。
可以说,你可以使用$year
和$dayOfYear
结果在后期处理中做同样的事情,因为那些也足以在客户端处理中重新构成日期对象
答案 1 :(得分:8)
虽然尼尔的回答确实有效,但我觉得这样做并不令人满意;它难以阅读,难以维护和缓慢。假设您从日期获得了价值(如OP中所述);如果您使用的是mongo 3.0或更高版本,使用$dateToString是最好的方法,但如果您遇到早期版本(像我一样),我认为您最好只是阅读字符串中的部分希望从日期字段(因为这些是零填充):
formattedTime: {
$concat: [
{ $substr: ["$timestamp", 0, 4] },
{ $substr: ["$timestamp", 5, 2] },
{ $substr: ["$timestamp", 8, 2] }
]
}
在我的情况下,我只想得到<hours>:<minutes>
(使用@ Neil的解决方案,这是一个正确的痛苦,因为我想零填充两个数字),这种做法特别好,但这种方式变得简单:{{1 }}
当然,我建议用一些命名常量替换幻数,以提高可读性。