अवधारणा की रूपरेखा
मैं मूल रूप से बहुत संक्षिप्त टिप्पणी में जो कह रहा था वह यह है कि बजाय प्रत्येक सेंसर "कुंजी" नाम के लिए एक अलग एकत्रीकरण क्वेरी जारी करने के लिए, आप इसे 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
ऑपरेटर एक "टर्नरी" ऑपरेटर है जिसका अर्थ है कि जहां पहली "अगर" शर्त true
. है , "फिर" दूसरा तर्क दिया जाता है, "अन्य" तीसरा तर्क दिया जाता है।
तो "Count"
. में त्रिगुट का बिंदु काम करना है:
- अगर फ़ील्ड है तो गिनती के लिए 1 लौटाएं
- अन्यथा 0 वापस करें जब वह वहां न हो
$group
के बाद
Average
. प्राप्त करने के लिए किया जाता है हम $divide
का इस्तेमाल करते हैं
अलग-अलग $project
मंच।
अंतिम परिणाम आपके द्वारा आपूर्ति की जाने वाली प्रत्येक कुंजी के लिए "औसत" है, और यह केवल उन दस्तावेज़ों के लिए मूल्यों और गणनाओं को जोड़ने पर विचार करता है जहां फ़ील्ड वास्तव में मौजूद थी।
इसलिए सभी कुंजियों को एक एग्रीगेशन स्टेटमेंट में डालने से प्रोसेसिंग में आपका बहुत समय और संसाधन बचेगा।
पाइपलाइन की गतिशील पीढ़ी
तो अजगर में इसे "गतिशील रूप से" करने के लिए, सूची से शुरू करें:
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]
जो "सेंसर" की दी गई सूची के लिए ऊपर दी गई पूरी सूची के समान उत्पन्न करता है।