计算集合中每个字段的现有值,奇怪的行为

时间:2017-06-28 08:38:19

标签: python mongodb aggregation-framework pymongo

我正在尝试获取文档中某些字段的现有值的计数,以便计算每年数据的这些值的平均值。由于我们注意到(in previous question)我们无法对我的案例使用$ avg聚合,因此我们决定使用sum / count操作。

以下是数据样本:

{
    "_id" : ObjectId("593ab6021ccb9b0c0fb226fd"),
    "timestamp" : ISODate("2016-11-17T12:36:00.000Z"),
    "CO2_CEL_SE_I_001" : 1210,
    "CO2_BUR_NE_I_001" : 880
}

{
    "_id" : ObjectId("593ab6021ccb9b0c0fb226fe"),
    "timestamp" : ISODate("2016-11-17T12:37:00.000Z"),
    "CO2_CEL_SE_I_001" : 1210,
    "CO2_BUR_NE_I_001" : 880
}

{
    "_id" : ObjectId("593ab6021ccb9b0c0fb226ff"),
    "timestamp" : ISODate("2016-11-17T12:38:00.000Z"),
    "CO2_CEL_SE_I_001" : 1210,
    "CO2_BUR_NE_I_001" : 880
}

{
    "_id" : ObjectId("593ab63a1ccb9b0c0fb3d3e5"),
    "timestamp" : ISODate("2016-02-01T19:26:00.000Z"),
    "CO2_CEL_SE_I_001" : 1080
}

{
    "_id" : ObjectId("593ab6021ccb9b0c0fb22700"),
    "timestamp" : ISODate("2016-11-17T12:39:00.000Z"),
    "CO2_CEL_SE_I_001" : 1210,
    "CO2_BUR_NE_I_001" : 880
}

然而,获得的结果似乎不是我期望得到的。就在下面是我的问题:

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

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

 project = {'$project':{}}

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

sort = {'$sort': {"_id":1}}

pipeline = [match, group, project, sort]

for doc in client["cleanData"]["maison2"].aggregate(pipeline):
print(doc)

以下是我的结果:

selectedSensors = [“CO2_BUR_NE_I_001”,“CO2_CEL_SE_I_001”]

{'_id': {'year': 2016}, 'CO2_BUR_NE_I_001-Count': 5, 'CO2_BUR_NE_I_001-Sum': 3520, 'CO2_CEL_SE_I_001-Count': 5, 'CO2_CEL_SE_I_001-Sum': 5920, 'CO2_BUR_NE_I_001-Avg': 704.0, 'CO2_CEL_SE_I_001-Avg': 1184.0}

selectedSensors = [“CO2_BUR_NE_I_001”]

{'_id': {'year': 2016}, 'CO2_BUR_NE_I_001-Count': 4, 'CO2_BUR_NE_I_001-Sum': 3520, 'CO2_BUR_NE_I_001-Avg': 880.0}

selectedSensors = [“CO2_CEL_SE_I_001”]

{'_id': {'year': 2016}, 'CO2_CEL_SE_I_001-Count': 5, 'CO2_CEL_SE_I_001-Sum': 5920, 'CO2_CEL_SE_I_001-Avg': 1184.0}

查询的行为很奇怪。当我在selectedSensor中定义多个元素的数组时,似乎每个字段的计数是最后一个字段计数的结果。当定义的数组由单个元素组合时,计数是正确的。

1 个答案:

答案 0 :(得分:1)

你误解了我在你自己的翻译中给你的代码。

所以这个:

group['$group'][chosenSensor+'-Count'] =
  {'$sum':{'$cond':[{'$ifNull':[True, False]}, 1, 0]}}

应该是:

group['$group'][chosenSensor+'-Count'] = {
  {'$sum':{'$cond':[{'$ifNull':['$'+chosenSensor, False]}, 1, 0]}

因为你写的是你要求$ifNull来评估总是存在的True的布尔值,而不是正确的表达式,它应该是当前的"字段",我们需要测试它是否存在。

所以发生的事情是这些领域总是"总是"被计算在内,这当然是"平均值"我们试图避免的问题。