2016-10-04 54 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