web-dev-qa-db-ja.com

MongoDBでのデータ型変換

MongoDBにDocumentというコレクションがあります。このコレクションのドキュメントには、CreationDateと呼ばれるフィールドがISO日付タイプに格納されています。私の仕事は、1日に作成されたドキュメントの数を数え、その数で非同期に並べ替えることです。出力形式は[{_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}}
);

コードは私に以下のようなエラーを与えます:

$concat only supports strings, not NumberInt32

これは、$ year、$ month、および$ dayOfMonthがすべて数値を返すためです。 _idフィールドをオブジェクトとして作成し、アプリケーションレベルで目的の形式に再フォーマットすることができます。

しかし、技術的な観点から、2つの質問があります。

  1. MongoDBシェルで数値を文字列に変換する方法は?この場合、$ yearの出力は文字列に変換され、$ concatで使用できます。

  2. ISODate出力をさまざまな日付形式にフォーマットするより良い方法はありますか?多くの場合、ISODateの特定の部分(たとえば、日付コンポーネントや時間部分)のみが必要です。これを達成するためのMongoDb組み込みオペレーターはありますか?

アドバイスを事前にありがとう。

25
Lee

$concat を使用してこれを行うことができますが、最初に $substr 、2桁の場合も処理します。

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

おそらく日付の計算を代わりに使用する方が良いかもしれません。これはエポックのタイムスタンプ値を返しますが、後処理で日付オブジェクトを操作するのは簡単です:

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 } }
])
30
Neil Lunn

ISODateをさまざまな日付形式に変換するもう1つの簡単な方法は、 $ dateToString集計演算子 を使用することです。

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

MONGO> = 3.0(〜2015以降)

私のように、2017年にこの質問に出くわした貧しい魂がいる場合:Mongo 3.0以降、 dateToString 演算子が利用可能になりました

つまり、適切なDate()があれば、簡単に実行できるはずです。

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

日付以外のフィールドに日付が格納されている場合(うれしい!)、プロジェクトステップで新しいDate()オブジェクトを作成できます。私の場合、日付はミリ秒(整数)の数として格納され、ミリ秒数を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}}
);
4
user3616725

ニールの答えはその権利ですが、少しバグがあります。条件文(月と日の数の先頭に0を付ける必要があるかどうかを確認する)は$gtではなく$lteです。

$lteを使用すると、1桁の月と日のみに0が付加されます。

例:2014-10 - 3、2014 - 8 - 3。

4
joaquim.adraz

日付形式を「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]}]}}},
]);
2
fabien0102