Nástin konceptu
To, co jsem v podstatě řekl ve velmi krátkém komentáři, je, že místo pro zadání samostatného agregačního dotazu pro každý název „klíče“ senzoru jej můžete vložit do JEDNOHO , pokud správně vypočítáte „průměry“.
Samozřejmě problém ve vašich datech je, že "klíče" nejsou přítomny ve všech dokumentech. Abychom získali správný „průměr“, nemůžeme jednoduše použít $avg
protože by počítal „VŠECHNY“ dokumenty, ať už byl klíč přítomen nebo ne.
Takže místo toho rozdělíme "matematický" a provedeme $group
pro celkový Count
a celkový Sum
od každého klíče jako první. Toto používá $ifNull
otestovat přítomnost pole a také $cond
pro alternativní hodnoty pro návrat.
.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
Operátor je "ternární" operátor, což znamená, že první podmínka "if" je true
, "pak" je vrácen druhý argument, "else" je vrácen třetí argument.
Tedy bod trojky v "Count"
je cvičit:
- Pokud tam pole je, vraťte 1 jako počet
- Jinak vraťte 0, když tam není
Po $group
je hotovo, abyste získali Average
používáme $divide
na dvou číslech vytvořených pro každý klíč v samostatném $project
fázi.
Konečným výsledkem je „průměr“ pro každý klíč, který zadáte, a to uvažovalo pouze o přidání hodnot a počtů pro dokumenty, kde se pole skutečně nacházelo.
Takže umístění všech klíčů do jediného agregačního příkazu vám ušetří spoustu času a prostředků na zpracování.
Dynamické generování potrubí
Chcete-li to provést "dynamicky" v pythonu, začněte se seznamem:
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]
Což generuje totéž jako úplný seznam výše pro daný seznam „senzorů“.