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

2023-12-04

我得到的数据集如下:

{
    "_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”、一个“时间戳”和多个传感器字段。传感器数量不一致。通过界面,我选择了许多想要包含在查询中的传感器。该选择存储在一个列表中,其中每一项都是传感器的名称。

例子 :

self.chosenSensors = ["Technique-Electrique_VMC Aldes_Power4[W]", "Technique-Electrique_VMC Unelvent_Power5[W]"]

我想计算每个所选传感器的平均值。我已经做到了,但我对每个传感器进行了查询。

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

page2.currentColl].aggregate([{"$match":{chosenSensor:{"$exists": True}}}, {"$group":{"_id":{"year":{"$year":"$timestamp"}, "month":{"$month":"$timestamp"}}, "average":{"$avg": chosenSensorAverage}}}])

结果(每个平均值都在新文档中):

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}

我想要得到的是以下内容:

{
    "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 来确定何时递增的“总和”。然后你 将在 $group 管道阶段“之后”进行 $divide 以获得最终结果 “平均的”。

如前所述,“关键名称”对我来说似乎是更大的问题,并且会 通过将它们移动到元素内的“值”可能会更好地处理 一个数组的

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


概念概要

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

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

因此,我们将“数学”分解,然后做一个$group为总计Count和总计Sum首先是每个键。这使用$ifNull测试该场的存在,并且还$cond替代要返回的值。

.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"
      ]
    }
  }}
])

The $cond运算符是“三元”运算符,这意味着第一个“if”条件是true,“then”返回第二个参数,“else”返回第三个参数。

所以三元的要点是"Count"是要解决:

  • 如果该字段存在,则返回 1 作为计数
  • 否则当不存在时返回0

之后$group完成后,为了得到Average we use $divide为每个键生成的两个数字$project stage.

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

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


管道的动态生成

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

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]

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

文档中键不同的多个字段平均聚合 的相关文章

随机推荐