2012-10-20 11 views
5

私はこのような単純なデシベルのレイアウトがあります。はMongoDBの凝集に数と平均を計算

client 
    id 
    sex (male/female) 
    birthday (date)  

client 
    id 
    sex (male/female) 
    birthday (date) 

(...) 

は私が持っているどのように多くの男性と女性のクライアント出力aggregationコマンドを記述しようとしている、と私男性と女性の平均年齢を出力することもできますが、私は同じコマンドでこれを行うことができないのでしょうか、2つの別々のものが必要ですか?

// Count of males/females, average age 
Clients.aggregate({ 
    $project : {"sex"  : 1, 
      "sexCount" : 1, 
      "birthday" : 1, 
      "avgAge" : 1 
       } 
    }, 
    { 
     $match: {"sex": {$exists: true}} 
    }, 
    { 
     $group: { 
        _id  : "$sex", 
      sexCount : { $sum: 1 }, 
      avgAge : { $avg: "$birthday" }, 
      } 
    }, 
    { $sort: { _id: 1 } } 
    , function(err, sex_dbres) { 
      if (err) 
       throw err; 
      else{ 
       (...) 
      } 
     });   

上記のコードでは、私は男性/女性のカウントを取得しますが、avgAgeは0として表示されます。

感謝

+0

最初の手順では、$ groupステップで計算するフィールドであるため、フィールドsexCountまたはavgAgeを投影する必要はありません。 –

答えて

4

は、日付オブジェクトは、「平均化」することはできませんが、数字ができます。あなたは、あなたの日付をタイムスタンプ値に変換し、それから平均を見つけることができます。しかしそれは平均的な年齢ではありませんが、集計関数の外で現在の日付から結果を差し引く必要があります。

もう1つの選択肢は、日付の年の部分のみを使用して年齢を計算できると仮定することです(つまり、2000年12月1日に生まれた場合、今日のレポートでは12歳になります)。この場合、date operatorsを使用して年の値を抽出することができます。

$project : {"sex"  : 1, 
      "sexCount" : 1, 
      "year" : {$year: "$birthday"}, 
      } 
}, 
$project : {"sex"  : 1, 
      "sexCount" : 1, 
      "age" : {$subtract: [2012, '$year']}, 
      } 
}, 
+0

ありがとうございます。誕生日が文字列( "Sat May 22 1982 00:00:00 GMT + 0200")として保存されていることが分かりました。それを数字でキャストすることは可能ですか?私はちょうど年の部分を得るためにsubstrをやってみましたが、それからあなたが提案する$減算をするために数字に変えることに問題があります。 これが難しい場合は、フィールドを日付にすることができます。 –

+0

変換は集約フレームワークの一部ではありません。任意のJavaScriptコードを記述できるMapReduceを使用するか、データベースを実行してすべての日付を変換する必要があります。 – Dmitry

+0

ありがとう!私は別のフィールドに年を抽出し、今すぐ簡単に平均を行うことができます。 –

6

ドミトリーが掲載され、あなたがちょうどあなたの$groupステップでストレートavgAge:{$avg:"$age"}を行うことができ、(元の文書に年齢を格納した場合の答えは非常に簡単になります。

集約Frameworkはいえ、かなり気の利いで、あなたは「その場で」この欠落している年齢のフィールドを計算することができ、多くのクールな演算子があり

私はそれが起こっているのかを確認する方が簡単ですので、変数に集計の各ステップを保存するつもりです:。

> db.client.find({},{_id:0}) 
{ "sex" : "male", "bday" : ISODate("2000-02-02T08:00:00Z") } 
{ "sex" : "male", "bday" : ISODate("1987-02-02T08:00:00Z") } 
{ "sex" : "female", "bday" : ISODate("1989-02-02T08:00:00Z") } 
{ "sex" : "female", "bday" : ISODate("1993-11-02T08:00:00Z") } 
> db.client.aggregate([ project1, project2, group, project3 ]) 
{ 
    "result" : [ 
     { 
      "sex" : "female", 
      "total" : 2, 
      "averageAge" : 21.34109589041096 
     }, 
     { 
      "sex" : "male", 
      "total" : 2, 
      "averageAge" : 19.215068493150685 
     } 
    ], 
    "ok" : 1 
} 
> 

これは単純ではない理由は、現在の集約フレームワークは、日付の直接の減算をサポートしていないです:

today = new Date(); 
// split today and bday into numerical year and numerical day-of-the-year 
project1= { 
    "$project" : { 
     "sex" : 1, 
     "todayYear" : { 
      "$year" : today 
     }, 
     "todayDay" : { 
      "$dayOfYear" : today 
     }, 
     "by" : { 
      "$year" : "$bday" 
     }, 
     "bd" : { 
      "$dayOfYear" : "$bday" 
     } 
    } 
}; 
// calculate age in days by subtracting bday in days from today in days 
project2 = { 
    "$project" : { 
     "sex" : 1, 
     "age" : { 
      "$subtract" : [ 
       { 
        "$add" : [ 
         { 
          "$multiply" : [ 
           "$todayYear", 
           365 
          ] 
         }, 
         "$todayDay" 
        ] 
       }, 
       { 
        "$add" : [ 
         { 
          "$multiply" : [ 
           "$by", 
           365 
          ] 
         }, 
         "$bd" 
        ] 
       } 
      ] 
     } 
    } 
}; 
// sum up for each sex the count and compute avg age (in days) 
group = { 
    "$group" : { 
     "_id" : "$sex", 
     "total" : { 
      "$sum" : 1 
     }, 
     "avgAge" : { 
      "$avg" : "$age" 
     } 
    } 
}; 
// divide days by 365 to get age in years. 
project3 = { 
    "$project" : { 
     "_id" : 0, 
     "sex" : "$_id", 
     "total" : 1, 
     "averageAge" : { 
      "$divide" : [ 
       "$avgAge", 
       365 
      ] 
     } 
    } 
}; 

は今、あなたは、集約を実行することができます。次回のメジャーリリースの対象となるhttps://jira.mongodb.org/browse/SERVER-6239に投票してください。一度実装されると、日付を直接減算できるはずです(この場合はおそらく適切な単位に変換する必要があります)。

+0

もちろん、これを行う別の方法は、bdayを日に変換し、グループステップの最終的なプロジェクトの計算時間を今日の日から365で除算した日数を引いたものにすることです。 –

+0

Thanks Asya、上記のように。 –