如何将数字1格式化为字符串“01”进行聚合?

时间:2014-08-04 08:50:50

标签: mongodb mongodb-query aggregation-framework

我正在尝试以" YYYYMMDD"的形式创建聚合键。基于我的文档中的日期字段。但是,使用$month$dayOfMonth运算符,我只会返回数字,而无法将它们格式化为前导零(此外,我无法连接数字)。

由于后者的阻塞性,我更喜欢聚合Map / Reduce。有什么想法吗?

2 个答案:

答案 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 }}

当然,我建议用一些命名常量替换幻数,以提高可读性。