コンセプトの概要
非常に短いコメントで基本的に言っていたのは、代わりに センサーの「キー」名ごとに個別の集計クエリを発行する場合は、 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"
]
}
}}
])
$cond
演算子は「三項」演算子です。これは、最初の「if」条件がtrue
であることを意味します。 、"then" 2番目の引数が返され、"else"3番目の引数が返されます。
したがって、"Count"
の3項のポイント 解決することです:
- フィールドが存在する場合は、カウントに1を返します
- それ以外の場合は、存在しない場合は0を返します
$group
の後
Average
を取得するために行われます $divide
を使用します
別々の$project
ステージ。
最終結果は、提供するすべてのキーの「平均」であり、これは、フィールドが実際に存在するドキュメントの値とカウントを追加することのみを考慮したものです。
したがって、すべてのキーを1つの集計ステートメントに入れると、処理にかかる時間とリソースを大幅に節約できます。
パイプラインの動的生成
したがって、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]
これは、「センサー」の特定のリストについて、上記の完全なリストと同じものを生成します。