首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >文档中键不同的多个字段的平均聚合

文档中键不同的多个字段的平均聚合
EN

Stack Overflow用户
提问于 2017-06-23 09:02:50
回答 1查看 193关注 0票数 1

我得到的数据如下:

代码语言:javascript
复制
{
    "_id" : ObjectId("592d4f43d69b643ac0cb9148"),
    "timestamp" : ISODate("2017-03-01T16:58:00.000Z"),
    "Technique-Meteo_Direction moyenne du vent_Mean value wind direction[]" : 0.0,
   "Technique-Meteo_Précipitations_Precipitation status[]" : 0.0,
    "Technique-Meteo_Direction du vent_Wind direction[]" : 0.0
}

/* 5 */
{
    "_id" : ObjectId("592d4f43d69b643ac0cb9149"),
    "timestamp" : ISODate("2017-03-01T17:09:00.000Z"),
    "Technique-Meteo_Direction moyenne du vent_Mean value wind direction[]" : 0.0,
    "Technique-Meteo_Précipitations_Precipitation status[]" : 0.0,
   "Technique-Meteo_Direction du vent_Wind direction[]" : 0.0
}

/* 6 */
{
    "_id" : ObjectId("592d3a6cd69b643ac0cae395"),
    "timestamp" : ISODate("2017-01-30T09:31:00.000Z"),
    "Technique-Electrique_Prises de Courant_Power1[W]" : 14.0,
    "Technique-Electrique_Eclairage_Power2[W]" : 360.0,
    "Technique-Electrique_Electroménager_Power3[W]" : 0.0,
    "Technique-Electrique_VMC Aldes_Power4[W]" : 14.0,
    "Technique-Electrique_VMC Unelvent_Power5[W]" : 8.0
}

/* 7 */
{
    "_id" : ObjectId("592d3a6cd69b643ac0cae396"),
    "timestamp" : ISODate("2017-01-30T09:32:00.000Z"),
    "Technique-Electrique_Prises de Courant_Power1[W]" : 15.0,
    "Technique-Electrique_Eclairage_Power2[W]" : 365.0,
    "Technique-Electrique_Electroménager_Power3[W]" : 0.0,
    "Technique-Electrique_VMC Aldes_Power4[W]" : 14.0,
    "Technique-Electrique_VMC Unelvent_Power5[W]" : 8.0
}

有一个"_id",一个“时间戳”和多个传感器字段。传感器的数量不一致。有了接口,我选择了许多传感器,我想要包括在我的查询。此选项存储在一个列表中,其中每个项都是传感器的名称。

例子:

代码语言:javascript
复制
self.chosenSensors = ["Technique-Electrique_VMC Aldes_Power4[W]", "Technique-Electrique_VMC Unelvent_Power5[W]"]

我想计算每个选定传感器的平均值。我已经做过了,但是我为每个传感器做了一个查询。

在下面的示例中,我将向您展示这一点。(不要考虑日期聚合,这是下一步)

代码语言:javascript
复制
page2.currentColl].aggregate([{"$match":{chosenSensor:{"$exists": True}}}, {"$group":{"_id":{"year":{"$year":"$timestamp"}, "month":{"$month":"$timestamp"}}, "average":{"$avg": chosenSensorAverage}}}])

结果(每个平均数都在一份新的文件中):

代码语言:javascript
复制
RDC-ChambreEnfants_CO2_GAS_CONCENTRATION[ppm]
{'_id': {'year': 2017, 'month': 4}, 'average': 1475.3685814315352}
{'_id': {'year': 2017, 'month': 3}, 'average': 1374.3771154414906}
RDC-ChambreEnfants_Humidité_HUMIDITY[%]
{'_id': {'year': 2017, 'month': 4}, 'average': 37.55591753379364}
{'_id': {'year': 2017, 'month': 3}, 'average': 37.459350662153724}

我想得到的是:

代码语言:javascript
复制
{
    "Avg_Technique-Meteo_Direction moyenne du vent_Mean value wind direction[]" : 0.0,
    "Avg_Technique-Meteo_Précipitations_Precipitation status[]" : 0.0,
    "Avg_Technique-Meteo_Direction du vent_Wind direction[]" : 0.0
    "Avg_Technique-Electrique_Prises de Courant_Power1[W]" : 14.5,
    "Avg_Technique-Electrique_Eclairage_Power2[W]" : 362.5,
    "Avg_Technique-Electrique_Electroménager_Power3[W]" : 0.0,
    "Avg_Technique-Electrique_VMC Aldes_Power4[W]" : 14.0,
    "Avg_Technique-Electrique_VMC Unelvent_Power5[W]" : 8.0
}

有人给了我一个提示(尼尔·伦恩):

您可能会使语句更长,并使用$ifNull获取每个语句的“计数”和“和”,以确定何时增加。然后,您将在“$divide”之后的“$group管道阶段”获得最终的“平均值”。 如前所述,对我来说,“键名”似乎是更大的问题,通过将它们移到数组元素中的“值”可能会更好。

对我来说,第一个问题是我不知道如何在查询中使用我的传感器列表。其他问题可能会在这个问题解决之后出现。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-06-23 09:32:48

概念大纲

我在非常简短的评论中基本上是这样说的:而不是,用于为每个传感器的“键”名称发出单独的聚合查询,只要您正确计算“平均值”,就可以将其放入ONE中。

当然,数据中的问题是“键”并不存在于所有文档中。因此,为了得到正确的“平均值”,我们不能只使用$avg,因为它会计算“所有”文档,不管密钥是否存在。

因此,我们将“数学”分解,首先为每个键的总Count和总Sum做一个Sum。这使用$ifNull测试字段的存在,并使用$cond测试要返回的替换值。

代码语言:javascript
复制
.aggregate([
  { "$match": {
    "$or": [
      { "Technique-Electrique_VMC Aldes_Power4[W]": { "$exists": True } },
      { "Technique-Electrique_VMC Unelvent_Power5[W]": { "$exists": True } }
    ]
  }}
  { "$group":{
    "_id":{
      "year":{ "$year":"$timestamp" },
      "month":{ "$month":"$timestamp" }
    },
    "Technique-Electrique_VMC Aldes_Power4[W]-Sum": { 
      "$sum": { 
        "$ifNull": [ "$Technique-Electrique_VMC Aldes_Power4[W]", 0 ]
      }
    },
    "Technique-Electrique_VMC Aldes_Power4[W]-Count": { 
      "$sum": { 
        "$cond": [
          { "$ifNull": [ "$Technique-Electrique_VMC Aldes_Power4[W]", false ] },
          1,
          0
        ]
      }
    },
    "Technique-Electrique_VMC Unelvent_Power5[W]-Sum": {
      "$sum": { 
        "$ifNull": [ "$Technique-Electrique_VMC Unelvent_Power5[W]", 0 ]
      }
    },
    "Technique-Electrique_VMC Unelvent_Power5[W]-Count": {
      "$sum": {
        "$cond": [ 
          { "$ifNull": [ "$Technique-Electrique_VMC Unelvent_Power5[W]", false ] },
          1,
          0
        ]
      }
    }
  }},
  { "$project": {
    "Technique-Electrique_VMC Aldes_Power4[W]-Avg": {
      "$divide": [
        "$Technique-Electrique_VMC Aldes_Power4[W]-Sum",
        "$Technique-Electrique_VMC Aldes_Power4[W]-Count"
      ]
    },
    "Technique-Electrique_VMC Unelvent_Power5[W]-Avg": {
      "$divide": [
        "Technique-Electrique_VMC Unelvent_Power5[W]-Sum",
        "Technique-Electrique_VMC Unelvent_Power5[W]-Count"
      ]
    }
  }}
])

$cond操作符是一个“三元”操作符,意思是第一个"if“条件是true,然后”第二个参数返回“,”否则“返回第三个参数。

因此,"Count"中三元结构的要点是计算出:

  • 如果字段在那里,则返回1进行计数。
  • 否则,当不存在时返回0。

在完成$group之后,为了获得Average,我们在单独的$project阶段中为每个键生成的两个数字上使用了$divide

最终的结果是您提供的每一个键的“平均值”,这只考虑了为实际存在字段的文档添加值和计数。

因此,将所有键放在一个聚合语句中,将节省大量的时间和处理资源。

管道动态生成

因此,要在python中“动态”执行此操作,请从下面的列表开始:

代码语言:javascript
复制
sensors = ["Technique-Electrique_VMC Aldes_Power4[W]", "Technique-Electrique_VMC Unelvent_Power5[W]"]

match = { '$match': { '$or': map(lambda x: { x: { '$exists': True } },sensors) } }

group = { '$group': { 
  '_id': {
    'year': { '$year': '$timestamp' },
    'month': { '$month':'$timestamp' }
  }
}}

project = { '$project': {  } }

for k in sensors:
  group['$group'][k + '-Sum'] = {
    '$sum': { '$ifNull': [ '$' + k, 0 ] }
  }
  group['$group'][k + '-Count'] = {
    '$sum': { '$cond': [ { '$ifNull': [ '$' + k, False ] }, 1, 0 ]  }
  }
  project['$project'][k + '-Avg'] = {
    '$divide': [ '$' + k + '-Sum', '$' + k + '-Count' ]
  }

pipeline = [match,group,project]

它为给定的“传感器”列表生成与上面完整列表相同的内容。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44717343

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档