Phác thảo Khái niệm
Về cơ bản, điều tôi đã nói trong nhận xét rất ngắn gọn là thay vào đó để đưa ra một truy vấn tổng hợp riêng biệt cho mọi tên "khóa" cảm biến, bạn có thể đặt nó vào ONE , miễn là bạn tính toán "trung bình" một cách chính xác.
Tất nhiên vấn đề trong dữ liệu của bạn là các "chìa khóa" không có trong tất cả các tài liệu. Vì vậy, để có được "mức trung bình" chính xác, chúng ta không thể chỉ sử dụng $avg
vì nó sẽ tính "TẤT CẢ" tài liệu, cho dù khóa có xuất hiện hay không.
Vì vậy, thay vào đó, chúng tôi chia nhỏ "toán học" và thực hiện $group
cho Tổng Count
và tổng Sum
của mỗi khóa đầu tiên. Điều này sử dụng $ifNull
để kiểm tra sự hiện diện của trường và cả $cond
để trả về các giá trị thay thế.
.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
toán tử là một toán tử "bậc ba" có nghĩa là trong đó điều kiện "nếu" đầu tiên là true
, "then" đối số thứ hai được trả về, "else" đối số thứ ba được trả về.
Vì vậy, điểm của bậc ba trong "Count"
là để làm việc:
- Nếu trường ở đó thì trả về 1 cho số lượng
- Ngược lại, trả về 0 khi nó không có ở đó
Sau $group
là xong, để nhận được Average
chúng tôi sử dụng $divide
trên hai số được tạo cho mỗi khóa trong một $project
sân khấu.
Kết quả cuối cùng là "trung bình" cho mọi khóa mà bạn cung cấp và điều này chỉ được coi là thêm giá trị và số lượng cho các tài liệu mà trường thực sự có mặt.
Vì vậy, đặt tất cả các khóa trong một câu lệnh tổng hợp sẽ giúp bạn tiết kiệm rất nhiều thời gian và tài nguyên để xử lý.
Tạo động lực của đường ống
Vì vậy, để thực hiện điều này "động" trong python, hãy bắt đầu với danh sách:
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]
Điều này tạo ra giống như danh sách đầy đủ ở trên cho một danh sách "cảm biến" nhất định.