我在数据库中有如下记录:
{
"_id" : ObjectId("592d4f43d69b643ac0cb9149"),
"timestamp" : "2017-03-01 17:09:00",
"Technique-Meteo_Direction moyenne du vent_Mean value wind direction[]" : 0.0,
"Technique-Meteo_Précipitations_Precipitation status[]" : 0.0,
"Technique-Meteo_Direction du vent_Wind direction[]" : 0.0
}
{
"_id" : ObjectId("592d3a6cd69b643ac0cae395"),
"timestamp" : "2017-01-30 09:31:00",
"Technique-Electrique_Prises de Courant_Power1[W]" : 14.0,
"Technique-Electrique_Eclairage_Power2[W]" : 360.0,
"Technique-Electrique_Electroménager_Power3[W]" : 0.0,
"Technique-Electrique_VMC Aldes_Power4[W]" : 14.0,
"Technique-Electrique_VMC Unelvent_Power5[W]" : 8.0
我的时间戳是一个简单的字符串,由于其他算法的更改量,我不愿意接触。 但是,我想做一些平均操作。实际上,其他字段是带有测量值的传感器名称。我每分钟有一条记录,我希望在一小时,一天或一个月内平均这些值。
就在此之前,我创建了一个查询来计算一个字段每月现有值的数量
countExistingPerMonth = client[page1.currentDB][page2.currentColl].find({"$and":[{"timestamp":{"$regex": regexExpression}}, {chosenSensor:{"$exists": True}}]}, temp_doc).count()
我使用$ regex表达式查找与所选月份匹配的文档。
有没有办法使用这种方法进行平均操作?
我试着做点什么(下面)。我也尝试使用正则表达式进行聚合,但这是不可能的。
self.sensorsStats = []
for chosenSensor in self.chosenSensors:
countPerMonth = []
years = []
incre_year = int(page5.combo_startYear.get())
if (incre_year<=int(page5.combo_endYear.get())):
while(incre_year!=(int(page5.combo_endYear.get())+1)):
years.append(str(incre_year))
incre_year += 1
for year in years:
for month in ["01","02","03","04","05","06","07","08","09","10","11","12"]:
regexExpression = '^'+year+'-'+month+'-..'
test = client[page1.currentDB][page2.currentColl].aggregate([{"$match":{"timestamp":{"$regex": regexExpression}}}, {"$group":{"_id":chosenSensor, "average":{"$avg":{chosenSensor}}}}])
答案 0 :(得分:1)
实际上你应该&#34;应该&#34;在这里修复时间戳字符串。但它们至少在词汇顺序中排在第二位。由于&#34; yyyy-dd-mm&#34; ISO Strings中固有的格式。
因此,由于它们具有固定长度,我们实际上可以使用聚合框架在服务器端聚合上聚合它们。
对五月份进行日期选择抽样:
cursor = client[page1.currentDB][page2.currentColl].aggregate([
{ "$match": {
"Technique-Meteo_Direction moyenne du vent_Mean value wind direction[]":
{ "$exists": True },
"timestamp": {
"$gte": "2017-05-01 00:00:00", "$lt": "2017-06-01 00:00:00"
}
}},
{ "$group": {
"_id": {
"$substr": [ "$timestamp", 0, 10 ]
},
"average":
{ "$avg": "$Technique-Meteo_Direction moyenne du vent_Mean value wind direction[]" }
}}
])
这将得到每天的总数&#34;&#34;对于所选月份中的每一天。这依赖于字段的词汇值。相同的基本原则适用于此处的所有间隔。因此,您只需使用零值填充字符串,直到您想要选择的间隔。
同样适用于&#34;分组键&#34;这里,_id
的值应该同样是直到所需间隔的子字符串。幸运的是,字符串格式为&#34;零填充&#34;所以小于"10"
的值前面有"05"
中的零。同样,这维持了&#34;范围&#34;的词汇顺序。
这就是你应该瞄准的目标,我认为你应该在这里选择你的字段,以及为范围选择生成时间戳字符串。
但是你肯定可以通过$group
在实际值的[$substr][2]
部分来表示你所需的间隔,而不需要为每个间隔迭代多个查询调用来获得一些东西。让数据库为你做。
你的&#34;键&#34;然而,这是另一个问题,因为它们不一致,你似乎总是在迭代可能的&#34;关键名称&#34;并为所有这些人执行单独的聚合。你可以把陈述更长一些,然后得到&#34;计数&#34;和&#34;总和&#34;每个使用$ifNull
来确定何时递增。然后你会{&3}}&#34;&#34; $divide
管道阶段获得最终&#34;平均值&#34;。
在不知道完整范围的情况下,最后一点有点复杂,而且并非完全在你的问题中。所以我会把这个留给你解决,或者问一个单独的问题。
N.B 此处
$group
从MongoDB 3.4开始实际上已弃用。替换运算符为$substr
和$substrBytes
。此处使用的运算符现在被视为$substrCP
的别名,它们在代码页处理方面有所不同,以考虑&#34; length&#34;记录在案。您应该使用适合您的代码页,但"timestamp"
可能始终采用单字节编码。