MongoDB中的数据类型转换

Lee*_*Lee 25 mongodb mongodb-query aggregation-framework

我有一个名为Document in MongoDB的集合.此集合中的文档具有以ISO日期类型存储的名为CreationDate的字段.我的任务是计算每天创建的文档数量,并按异步数量排序.输出格式必须是[{_id:'yyyy-MM-dd',cnt:x}].我尝试使用如下聚合框架.

db.Document.aggregate( 
    , {$project: {_id:1, Year:{$year:'$CreationDate'}, Month:{$month:'$CreationDate'}, Date:{$dayOfMonth:'$CreationDate'}}}
    , {$group: {_id:{$concat:['$Year', '-', '$Month', '-', '$Date']}, cnt:{$sum:1}}}
    , {$sort:{'cnt':-1}}
);
Run Code Online (Sandbox Code Playgroud)

代码给出了如下错误:

$concat only supports strings, not NumberInt32
Run Code Online (Sandbox Code Playgroud)

我明白这是因为$ year,$ month和$ dayOfMonth都返回了数字.可以将_id字段组合为对象,并在应用程序级别以所需格式重新格式化它.

但从技术角度来看,我有两个问题:

  1. 如何在MongoDB shell中将数字转换为字符串?在这种情况下,$ year的输出可以转换为字符串并在$ concat中使用.

  2. 有没有更好的方法将ISODate输出格式化为各种日期格式?在许多情况下,我们只需要ISODate的某些部分,例如:日期组件或时间部分.是否有任何MongoDb内置运营商来实现这一目标?

提前感谢任何建议.

Nei*_*unn 29

你可以这样做,$concat但首先你需要转换为字符串$substr,也处理双位数字:

db.Document.aggregate([ 
    { "$group": { 
        "_id":{ 
            "$concat": [
                 { "$substr": [ { "$year": "$CreationDate" }, 0, 4 ] },
                 "-",
                 { "$cond": [
                     { "$gt": [ { "$month": "$CreationDate" }, 9 ] },
                     { "$substr": [ { "$month": "$CreationDate" }, 0, 2 ] },
                     { "$concat": [
                         "0",
                         { "$substr": [ { "$month": "$CreationDate" }, 0, 1 ] },
                     ]},
                 ]},
                 "-",
                 { "$cond": [
                     { "$gt": [ { "$dayOfMonth": "$CreationDate" }, 9 ] },
                     { "$substr": [ { "$dayOfMonth": "$CreationDate" }, 0, 2 ] },
                     { "$concat": [
                         "0",
                         { "$substr": [ { "$dayOfMonth": "$CreationDate" }, 0, 1 ] },
                     ]}
                 ]}
             ]
         },
         { "cnt": { "$sum": 1 } }
    }}
    { "$sort":{ "cnt" :-1 }}
]);
Run Code Online (Sandbox Code Playgroud)

可能更好的是仅使用日期数学,这会返回一个纪元时间戳值,但在后期处理中很容易使用日期对象:

db.Document.aggregate([
    { "$group": {
        "_id": {
            "$subtract": [
                { "$subtract": [ "$CreationDate", new Date("1970-01-01") ] },
                { "$mod": [
                    { "$subtract": [ "$CreationDate", new Date("1970-01-01") ] },
                    1000 * 60 * 60 * 24
                ]}
            ]
        },
        "cnt": { "$sum": 1 }
    }},
    { "$sort": { "cnt": -1 } }
])
Run Code Online (Sandbox Code Playgroud)

  • +1为``$ substr``.有点笨拙的是``$ concat``需要一个字符串,但``$ substr``并不是......有趣的"投射"方式. (5认同)

Joe*_*Joe 14

将ISODate转换为各种日期格式的另一种更简单的方法是使用$ dateToString聚合运算符.

db.collection.aggregate([
    { $group: {
        _id: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$CreationDate" } },
        count: { $sum: 1 }
    }},
    { $sort : { count: -1 }}
])
Run Code Online (Sandbox Code Playgroud)