12

「foo」という名前のコレクションのタイムスタンプでグループ化しようとしています { _id, TimeStamp }

db.foos.aggregate(
[
   {$group : { _id : new Date (Date.UTC({ $year : '$TimeStamp' },{ $month : '$TimeStamp' },{$dayOfMonth : '$TimeStamp'}))       }}
])

多くの日付が必要ですが、結果は 1 つの日付だけです。私が使用しているデータは正しいです (多くの foo と 1970 年以外の異なる日付があります)。日付の解析に問題がありますが、まだ解決できません。

{
    "result" : [ 
        {
            "_id" : ISODate("1970-01-01T00:00:00.000Z")
        }
    ],
    "ok" : 1
}

これを試しました:

db.foos.aggregate(
[
   {$group : { _id : { year : { $year : '$TimeStamp' }, month : { $month : '$TimeStamp' }, day : {$dayOfMonth : '$TimeStamp'} }, count : { $sum : 1 }       }},
   {$project : { parsedDate : new Date('$_id.year', '$_id.month', '$_id.day') , count : 1, _id : 0} }
])

結果 :

uncaught exception: aggregate failed: {
    "errmsg" : "exception: disallowed field type Date in object expression (at 'parsedDate')",
    "code" : 15992,
    "ok" : 0
}

そしてそれ:

db.foos.aggregate(
[
   {$group : { _id : { year : { $year : '$TimeStamp' }, month : { $month : '$TimeStamp' }, day : {$dayOfMonth : '$TimeStamp'} }, count : { $sum : 1 }       }},
   {$project : { parsedDate : Date.UTC('$_id.year', '$_id.month', '$_id.day') , count : 1, _id : 0} }
])

結果に日付が表示されない

{
    "result" : [ 
        {
            "count" : 412
        }, 
        {
            "count" : 1702
        }, 
        {
            "count" : 422
        }
    ],
    "ok" : 1
}
4

3 に答える 3

20
db.foos.aggregate(
    [   
        {   $project : { day : {$substr: ["$TimeStamp", 0, 10] }}},        
        {   $group   : { _id : "$day",  number : { $sum : 1 }}},
        {   $sort    : { _id : 1 }}        
    ]
)

日付によるグループ化は、集計フレームワークで 2 つの手順で実行できます。並べ替えが必要な場合は、結果を並べ替えるために追加の 3 番目の手順が必要です。

  1. $projectと組み合わせて$substr、各ドキュメントから ISODate オブジェクトの最初の 10 文字 (YYYY:MM:DD) を取得します (結果は、フィールド "_id" と "day" を持つドキュメントのコレクションです)。
  2. $group日ごとにグループ化し、一致するドキュメントごとに 1 を加算 (合計) します。
  3. $sort前の集約ステップからの日である「_id」による昇順 - ソートされた結果が必要な場合、これはオプションです。

db.twitter.ensureIndex( { TimeStamp: 1 } )このソリューションは、ISODate オブジェクトをオンザフライで文字列オブジェクトに変換するため、のようなインデックスを利用できません。大規模なコレクション (数百万のドキュメント) の場合、これはパフォーマンスのボトルネックになる可能性があるため、より洗練されたアプローチを使用する必要があります。

于 2014-05-16T13:57:58.290 に答える
13

最終出力で日付を ISODate タイプにするかどうかによって異なります。その場合は、次の 2 つのいずれかを行うことができます。

  1. $yearタイムスタンプから, $month,を抽出$dayOfMonthし、それらから新しい日付を再構築します (既に実行しようとしていますが、集計フレームワークでは機能しない構文を使用しています)。

  2. 元のタイムスタンプが ISODate() 型の場合、日付演算を実行して、タイムスタンプから時、分、秒、およびミリ秒を減算して、日に「丸められた」新しい日付を取得できます。

ここに 2 の例があります。

1. すべての日付が今年のものであると仮定していますが、最も古い日付に合わせて計算を簡単に調整できます。

project1={$project:{_id:0, 
                   y:{$subtract:[{$year:"$TimeStamp"}, 2013]},
                   d:{$subtract:[{$dayOfYear:"$TimeStamp"},1]}, 
                   TimeStamp:1, 
                   jan1:{$literal:new ISODate("2013-01-01T00:00:00")}
         } };
project2={$project:{tsDate:{$add:[
                       "$jan1",
                       {$multiply:["$y", 365*24*60*60*1000]},
                       {$multiply:["$d", 24*60*60*1000]}
         ] } } };

サンプルデータ:

db.foos.find({},{_id:0,TimeStamp:1})
{ "TimeStamp" : ISODate("2013-11-13T19:15:05.600Z") }
{ "TimeStamp" : ISODate("2014-02-01T10:00:00Z") }

集計結果:

> db.foos.aggregate(project1, project2)
{ "tsDate" : ISODate("2013-11-13T00:00:00Z") }
{ "tsDate" : ISODate("2014-02-01T00:00:00Z") }
于 2013-11-13T19:23:22.023 に答える
0

これは、私のプロジェクトの1つで使用するものです:

   collection.aggregate(
      // group results by date
      {$group : {
        _id : { date : "$date" }
        // do whatever you want here, like $push, $sum...
      }},

      // _id is the date
      {$sort : { _id : -1}},                        
      {$orderby: { _id : -1 }})
    .toArray()

$date は mongo の Date オブジェクトです。日付で索引付けされた結果を取得します。

于 2014-10-19T17:50:50.930 に答える