2016-05-31 22 views
1

集団になると私は本当に新しい人だから、これで助けてください。MongoDB集計AVG()

のは、私はこのような複数のドキュメント(時間の経過)を持っているとしましょう:

{ 
    "_id": ObjectId("574d6175da461e77030041b7"), 
    "hostname": "VPS", 
    "timestamp": NumberLong(1460040691), 
    "cpuCores": NumberLong(2), 
    "cpuList": [ 
    { 
     "name": "cpu1", 
     "load": 3.4 
    }, 
    { 
     "name": "cpu2", 
     "load": 0.7 
    } 
    ] 
}, 
{ 
    "_id": ObjectId("574d6175da461e77030041b7"), 
    "hostname": "VPS", 
    "timestamp": NumberLong(1460040700), 
    "cpuCores": NumberLong(2), 
    "cpuList": [ 
    { 
     "name": "cpu1", 
     "load": 0.4 
    }, 
    { 
     "name": "cpu2", 
     "load": 6.7 
    } 
    ] 
}, 
{ 
    "_id": ObjectId("574d6175da461e77030041b7"), 
    "hostname": "VPS", 
    "timestamp": NumberLong(1460041000), 
    "cpuCores": NumberLong(2), 
    "cpuList": [ 
    { 
     "name": "cpu1", 
     "load": 25.4 
    }, 
    { 
     "name": "cpu2", 
     "load": 1.7 
    } 
    ] 
} 

私はXの時間をかけて平均CPU負荷を取得したいのですが。ここで、Xは300秒に等しい。

  1. グラブお互い
  2. 計算の300秒以内にすべての文書:

    { 
        "avgCPULoad": "2.8", 
        "timestamp": NumberLong(1460040700) 
    }, 
    { 
        "avgCPULoad": "13.55", 
        "timestamp": NumberLong(1460041000) 
    } 
    

    avgCpuLoadは、次のように計算されます:1は、このように見える結果セットを得るでしょう上だから、例を挙げて

    平均:

    1. (((3.4+0.7)/2)+((0.4+6.7)/2))/2 = 2.8
    2. ((25.4+1.7)/2) = 13.55
  3. 選択したドキュメントから最後のタイムスタンプを追加します。

私はx時間ごとにどのようにすべてのドキュメントを取得しているのか知っています。これは次のように行われます:

db.Pizza.aggregate(
[ 
    { 
     $group: 
     { 
      _id: 
      { 
       $subtract: [ 
        '$timestamp', 
        { 
         $mod: ['$timestamp', 300] 
        } 
       ] 
      }, 
      'timestamp': {$last:'$timestamp'} 
     }, 
    { 
     $project: {_id: 0, timestamp:'$timestamp'} 
    } 
]) 

しかし、上記のように平均を計算するとどうなりますか? 私は$unwindでビットを試しましたが、私が望む結果を与えていません。

+0

がにスキーマの変更を検討してください(秒)5分間隔で割ったとき、あなたが得る残りの部分から秒単位でタイムスタンプを減算することによって推定されますあなたの '' cpuList ''フィールドに一貫したキーバリュー文書を埋め込んだドキュメントを持っている「cpuList」:[{名前: "cpu1"、負荷:3.4}、{名前: "cpu2"、負荷:0.7}] ' '$ avg'のような集合アキュムレータ演算子が有効になるように、' load'値を数値のものに変換する必要もあります。 – chridam

+0

なぜ私は負荷のプロパティの文字列を作った理由は、私はそれが精度の浮動小数点数を混乱させるだろう数値を作ったためだった。例えばphpの中では、floatは2小数で丸められました。私はそれをMongoに置くたびに、それは10のような2つの小数の代わりに、または実際に小さなオフセットを持つ何かを得ました。 – Baklap4

+0

@chridam Alrightはあなたの提案にあなたのスキーマを変更しました。平均を計算するためにクエリをどのように作成しますか? – Baklap4

答えて

1

あなたが希望する結果を得るために、以下の集約演算を実行する必要があります:5分間隔で

db.collection.aggregate([ 
    { "$unwind": "$cpuList" }, 
    { 
     "$group": { 
      "_id": {     
       "interval": { 
        "$subtract": [ 
         "$timestamp",       
         { "$mod": [ "$timestamp", 60 * 5 ] } 
        ] 
       } 
      },    
      "avgCPULoad": { "$avg": "$cpuList.load" }, 
      "timestamp": { "$max": "$timestamp" } 
     } 
    }, 
    { 
     "$project": { "_id": 0, "avgCPULoad": 1, "timestamp": 1 } 
    } 
]) 

上記の基平坦化文書を(数秒で描写される)。間隔キーは、実際のタイムスタンプが

サンプル出力

/* 1 */ 
{ 
    "avgCPULoad" : 13.55, 
    "timestamp" : NumberLong(1460041000) 
} 

/* 2 */ 
{ 
    "avgCPULoad" : 2.8, 
    "timestamp" : NumberLong(1460040700) 
} 
+1

タイムスタンプはミリ秒単位ではなく秒単位で表示されます。 – Baklap4

+0

@ Baklap4あなたは間違いないです。私はミリ秒ではなく秒を反映するように答えを更新しました。 – chridam

+0

mongoの中でラウンドする可能性はありますか? – Baklap4

1

解決策は、配列(cpulist)でunwindを使用することです。私はあなたのためのサンプルクエリを作った:

db.CpuInfo.aggregate([ 
    { 
     $unwind: '$cpuList' 
    }, 
    { 
     $group: { 
      _id:{ 
       $subtract:[ 
        '$timestamp', 
        {$mod: ['$timestamp', 300]} 
       ] 
      }, 
      'timestamp':{$last:'$timestamp'}, 
      'cpuList':{$avg:'$cpuList.load'} 
     } 
    } 
])