2016-10-04 6 views
2

ドキュメントの配列内の特定の値について平均:MongoDBの集合Iは、現在、以下の構造を有するデータベースに取り組んでい

{"_id" : ObjectId("1abc2"), 
"startdatetime" : ISODate("2016-09-11T18:00:37Z"), 
"diveValues" : [ 
    { 
     "temp" : 15.269, 
     "depth" : 0.0, 
    }, 
    { 
     "temp" : 14.779257384, 
     "depth" : 1.0, 
    }, 
    { 
     "temp" : 14.3940253165, 
     "depth" : 2.0, 
    }, 
    { 
     "temp" : 13.9225795455, 
     "depth" : 3.0, 
    }, 
    { 
     "temp" : 13.8214431818, 
     "depth" : 4.0, 
    }, 
    { 
     "temp" : 13.6899553571, 
     "depth" : 5.0, 
    } 
]} 

データベースは、水中での深さNメートルに関する情報、および所定のオン温度を有します深さこれは "diveValues"配列に格納されます。私は、月間平均と日平均の両方の日付間のすべての深度で平均化することに成功しています。私が深刻な問題を抱えているのは、過去6ヶ月間の毎月の平均値を1〜4メートルの深さにすることです。ここで

は、1月から6月までの各月の平均気温の一例であり、全ての深さのために:

に結果の
db.collection.aggregate(
    [ 
    {$unwind:"$diveValues"}, 
    {$match: 
     {'startdatetime': 
     {$gt:new ISODate("2016-01-10T06:00:29Z"), 
     $lt:new ISODate("2016-06-10T06:00:29Z")} 
     } 
     }, 

    {$group: 
     {_id: 
     { year: { $year: "$startdatetime" }, 
     month: { $month: "$startdatetime" }}, 
     avgTemp: { $avg: "$diveValues.temp" }} 
    }, 
    {$sort:{_id:1}} 
    ] 
) 

:今

{ "_id" : { "year" : 2016, "month" : 1 }, "avgTemp" : 7.575706502958313 } 
{ "_id" : { "year" : 2016, "month" : 3 }, "avgTemp" : 6.85037457740135 } 
{ "_id" : { "year" : 2016, "month" : 4 }, "avgTemp" : 7.215702831902588 } 
{ "_id" : { "year" : 2016, "month" : 5 }, "avgTemp" : 9.153453683614638 } 
{ "_id" : { "year" : 2016, "month" : 6 }, "avgTemp" : 11.497953009390237 } 

、私は方法を見つけ出すように見えることはできません同じ期間に平均温度を1〜4メートルにする。

私は希望の深さで値をグループ化しようとしていましたが、それを管理していませんでした。また、私が間違っていなければ、$ matchパイプラインはダイビングが1メートルと4メートルの値を持つ限りすべての深さを返すので、うまくいかないでしょう。

find()ツールを使用して、私は配列からの値を返すために$ sliceを使用していますが、aggregate()関数と一緒に成功しませんでした。

これを解決する方法はありますか?事前に感謝、多くの感謝!

答えて

0

あなたの$matchパイプラインを配置する必要があるだろう配列エントリーごとに文書を作成し、より多くのメモリー(総メモリー量の10%の集約パイプラインで使用可能なメモリーキャップ)を使用すると、処理時間を短縮するために「時間」が必要になります。したがって、パイプラインに入る文書の数を平らにすることを制限する方がよいでしょう。

db.collection.aggregate([ 
    { 
     "$match": { 
      "startdatetime": { 
       "$gt": new ISODate("2016-01-10T06:00:29Z"), 
       "$lt": new ISODate("2016-06-10T06:00:29Z") 
      }, 
      "diveValues.depth": { "$gte": 1, "$lte": 4 } 
     } 
    }, 
    { "$unwind": "$diveValues" }, 
    { "$match": { "diveValues.depth": { "$gte": 1, "$lte": 4 } } }, 
    { 
     "$group": { 
      "_id": { 
       "year": { "$year": "$startdatetime" }, 
       "month": { "$month": "$startdatetime" } 
      }, 
      "avgTemp": { "$avg": "$diveValues.temp" } 
     } 
    } 
]) 

あなたは全ての深さのためと1-4深さ範囲の平均臨時雇用者を含むように結果をしたい場合は、フィードに$cond tenary演算子を使用することになり、このパイプラインを実行する必要があります$avgオペレータは、深さの範囲に基づいて、グループ内の累積温度:それが動作するように

db.collection.aggregate([ 
    { 
     "$match": { 
      "startdatetime": { 
       "$gt": new ISODate("2016-01-10T06:00:29Z"), 
       "$lt": new ISODate("2016-06-10T06:00:29Z") 
      } 
     } 
    },  
    { "$unwind": "$diveValues" }, 
    { 
     "$group": { 
      "_id": { 
       "year": { "$year": "$startdatetime" }, 
       "month": { "$month": "$startdatetime" } 
      }, 
      "avgTemp": { "$avg": "$diveValues.temp" }, 
      "avgTempDepth1-4": { 
       "$avg": { 
        "$cond": [ 
         { 
          "$and": [ 
           { "$gte": [ "$diveValues.depth", 1 ] }, 
           { "$lte": [ "$diveValues.depth", 4 ] } 
          ] 
         }, 
         "$diveValues.temp", 
         null       
        ] 
       } 
      } 
     } 
    } 
]) 
+1

ありがとう、これはうまくいった。巻き戻す前に試合をすることについてのヒントをありがとう。 – Vegar

+0

@ヴェガール心配する必要はありません。最初から最後のパイプラインを使い終わったのは、驚くべきことですか? – chridam

+0

私の必要性のために、最初のものが私に最も適しています。しかし、私はそれが非常に教育的であることがわかっているので、あなたはそれらを両方書くと非常に感謝しています。 – Vegar

0

まず、日付$が一致オペレータshould be used at the beginning of the pipeline so that indexes can be usedです。今

、あなたはちょうどあなたが日付で行ったように、深さ間隔をフィルタリングする必要が質問に:

db.col.aggregate([ 
    {"$match": { 
     'startdatetime': { 
      "$gt": new ISODate("2016-01-10T06:00:29Z"), 
      "$lt": new ISODate("2016-11-10T06:00:29Z") 
     } 
    }}, 
    {"$unwind": "$diveValues"}, 
    {"$match": { 
     "diveValues.depth": { 
      "$gte": 1.0, 
      "$lt": 4.0 
     } 
    }}, 
    {"$group": { 
     "_id": { 
      "year": {"$year": "$startdatetime" }, 
      "month": {"$month": "$startdatetime" } 
     }, 
     "avgTemp": { "$avg": "$diveValues.temp" }} 
    } 
]) 

これは、あなただけで選ばれた深さ間隔の平均値が得られます。それはそれぞれのコピーを生成するので、コレクション全体に$unwind操作を行うこととして$unwindoptimizeにご集合操作が潜在的にいくつかのパフォーマンス上の問題を引き起こす可能性がある前に

+1

どうもありがとう、これが見えます。また、アンワインドの配置についてのチップのおかげで。 – Vegar

関連する問題