2016-10-04 53 views
2

我目前正在對數據庫具有以下結構數組:MongoDB的合計 - 平均特定值的文件

{"_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米之間。

這裏是平均溫度爲每月從一月到六月的一個例子,對所有的深度:

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米的平均溫度。

我一直試圖按想要的深度對值進行分組,但沒有管理它 - 更多的時候是以不好的語法結束。此外,如果我沒有錯,只要潛水的值爲1米和4米,$匹配管道就會返回所有深度,這樣就不會起作用。使用find()工具我使用$ slice從數組中返回我想要的值 - 但沒有成功與aggregate()函數一起使用。

有沒有辦法解決這個問題?在此先感謝,非常感謝!

回答

0

你需要把你的$match管道之前$unwindoptimize您的聚集操作在整個集合做一個$unwind操作可能會導致一些性能問題,因爲它產生複印件各一份文件每個數組條目,並使用更多的內存(聚合管道佔總內存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

@Vegar不用擔心。出於好奇,你最終使用了哪條管線,第一條還是最後一條? – 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" }} 
    } 
]) 

這會給你平均只對選定的深度區間。

+1

非常感謝,這看起來像它的工作原理。另外,感謝關​​於展開位置的提示。 – Vegar