Data type conversion in MongoDB

后端 未结 5 1234
离开以前
离开以前 2020-12-29 04:16

I have a collection called Document in MongoDB. Documents in this collection have a field called CreationDate stored in ISO date type. My task is to count the number of docu

相关标签:
5条回答
  • 2020-12-29 04:29

    To convert date format to "xxxx-xx-xx"

    db.getCollection('analytics').aggregate([
     {$project: {
         day: {$dayOfMonth: "$createdAt"},
         month: {$month: "$createdAt"},
         year: {$year: "$createdAt"},
         }
      },
      {$project: {
          day: {$concat:["0", {$substr:["$day",0, 2]}]},
         month: {$concat:["0", {$substr:["$month",0, 2]}]},
         year: {$substr:["$year",0, 4]},
          }
      },
      {$project: {date: {$concat: [{$substr:["$year",0, 4]},"-", {$substr:["$month",0, 2]},"-", {$substr:["$day",0, 2]}]}}},
    ]);
    
    0 讨论(0)
  • 2020-12-29 04:32

    FOR MONGO >= 3.0 (after ~2015)

    In case some poor souls stumble across this question in 2017, like me: As of Mongo 3.0 there is now a dateToString operator available

    which means if you have proper Date()'s you should be able to do simply:

    db.Document.aggregate( 
        , {$project: {_id:1, CreationDate:1}
        , {$group: {
             _id : { $dateToString: { format: "%Y-%m-$d", date: "$CreationDate" } },
             cnt:{$sum:1}}}
        , {$sort:{'cnt':-1}}
    );
    

    For those of us who happen to have dates stored in non-date field (what joy!) you can create a new Date() object in the project step. In my case, the date was stored as a number of milliseconds (integer) and I add the number of milliseconds to the 0-Date.

    db.Document.aggregate( 
        , {$project: {
             _id:1, 
             CreationDate: {"$add": [ new Date(0), "$CreatedOn" ]}
    }
        , {$group: {
             _id : { $dateToString: { format: "%Y-%m-$d", date: "$CreationDate" } },
             cnt:{$sum:1}}}
        , {$sort:{'cnt':-1}}
    );
    
    0 讨论(0)
  • 2020-12-29 04:46

    You can do this with $concat but first you need to convert to a string via $substr, also handling the double digit case:

    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 }}
    ]);
    

    Possibly better is to just use date math instead, this returns an epoch timestamp value, but it is easy to work into a date object in post processing:

    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 } }
    ])
    
    0 讨论(0)
  • 2020-12-29 04:47

    Another easier way you can convert ISODate to various date formats is to use the $dateToString aggregation operator.

    db.collection.aggregate([
        { $group: {
            _id: { $dateToString: { format: "%Y-%m-%d %H:%M", date: "$CreationDate" } },
            count: { $sum: 1 }
        }},
        { $sort : { count: -1 }}
    ])
    
    0 讨论(0)
  • 2020-12-29 04:47

    Neil's answer its right to the point but has a little bug. In the conditionals (to check if the number of the month and day needs to be prepended with a 0) is not $gt but $lte.

    With $lte, only months and days with one digit will be prepended with 0.

    e.g: 2014-10-03, 2014-08-03.

    0 讨论(0)
提交回复
热议问题