Garis Besar Konsep
Apa yang pada dasarnya saya katakan dalam komentar yang sangat singkat adalah bahwa sebagai gantinya untuk mengeluarkan kueri agregasi terpisah untuk setiap nama "kunci" sensor, Anda dapat memasukkannya ke SATU , selama Anda menghitung "rata-rata" dengan benar.
Tentu saja masalah dalam data Anda adalah bahwa "kunci" tidak ada di semua dokumen. Jadi untuk mendapatkan "rata-rata" yang benar, kita tidak bisa hanya menggunakan $avg
karena itu akan menghitung "SEMUA" dokumen, apakah kuncinya ada atau tidak.
Jadi, alih-alih, kami memecah "matematika", dan melakukan $group
untuk Total Count
dan total Sum
masing-masing kunci terlebih dahulu. Ini menggunakan $ifNull
untuk menguji keberadaan bidang, dan juga $cond
ke nilai alternatif untuk kembali.
.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
operator adalah operator "ternary" yang artinya di mana kondisi "jika" pertama adalah true
, "maka" argumen kedua dikembalikan, "lain" argumen ketiga dikembalikan.
Jadi maksud dari ternary di "Count"
adalah untuk berolahraga:
- Jika kolom ada, kembalikan 1 untuk hitungan
- Jika tidak, kembalikan 0 jika tidak ada
Setelah $group
selesai, untuk mendapatkan Average
kami menggunakan $divide
pada dua angka yang dihasilkan untuk setiap kunci dalam $project
panggung.
Hasil akhirnya adalah "rata-rata" untuk setiap kunci yang Anda berikan, dan ini dianggap hanya menambah nilai dan jumlah untuk dokumen yang bidangnya benar-benar ada.
Jadi, menempatkan semua kunci dalam satu pernyataan agregasi akan menghemat banyak waktu dan sumber daya dalam pemrosesan.
Pembuatan Pipa Dinamis
Jadi untuk melakukan ini "secara dinamis" dengan python, mulailah dengan daftar:
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]
Yang menghasilkan sama dengan daftar lengkap di atas untuk daftar "sensor" tertentu.