Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python按日期范围求和值_Python_Mongodb_Mapreduce_Aggregation Framework - Fatal编程技术网

Python按日期范围求和值

Python按日期范围求和值,python,mongodb,mapreduce,aggregation-framework,Python,Mongodb,Mapreduce,Aggregation Framework,我有一个带有时间戳/日期时间和mongodb给定值的列表。 (来自mongodb的数据组织如下:) 我已将mongodb项转换为以下列表 清单项目(一天): 我有一种方法可以为我的数据生成一个很好的间隔: def date_span(start_date, end_date, data): delta = datetime.timedelta(hours=15) current_date = start_date.replace(minute=0) while curre

我有一个带有时间戳/日期时间和mongodb给定值的列表。 (来自mongodb的数据组织如下:)

我已将mongodb项转换为以下列表

清单项目(一天):

我有一种方法可以为我的数据生成一个很好的间隔:

def date_span(start_date, end_date, data):
    delta = datetime.timedelta(hours=15)
    current_date = start_date.replace(minute=0)
    while current_date < end_date:
        yield current_date
        current_date += delta
def date_span(开始日期、结束日期、数据):
delta=datetime.timedelta(小时=15)
当前日期=开始日期。替换(分钟=0)
当前日期<结束日期:
当前日期的收益率
当前日期+=增量

但是,如何将列表项的数据与新的timespan项合并并求和?我想总结一下给定时间的值。例如,总结每小时、每天、每周、每月、每年的值。有什么提示吗

数据当前的存储方式在这方面对您没有帮助。您最好更进一步地进行“转换”,并以这种方式存储数据:

{“时间戳”:ISODate(“2014-01-01T00:00:00.000Z”),“realPower”:545.5}
{“timestamp”:ISODate(“2014-01-01T00:15:00.000Z”),“realPower”:614.5}
{“timestamp”:ISODate(“2014-01-01T00:30:00.000Z”),“realPower”:586.25}
{“timestamp”:ISODate(“2014-01-01T00:45:00.000Z”),“realPower”:565.75}
{“timestamp”:ISODate(“2014-01-01T01:00:00.000Z”),“realPower”:574.5}
{“timestamp”:ISODate(“2014-01-01T01:15:00.000Z”),“realPower”:549.5}
{“timestamp”:ISODate(“2014-01-01T01:30:00.000Z”),“realPower”:564}
{“timestamp”:ISODate(“2014-01-01T01:45:00.000Z”),“realPower”:545.75}
{ ... }
{“timestamp”:ISODate(“2014-01-01T23:00:00.000Z”),“realPower”:604.75}
{“timestamp”:ISODate(“2014-01-01T23:15:00.000Z”),“realPower”:605}
{“timestamp”:ISODate(“2014-01-01T23:30:00.000Z”),“realPower”:605}
{“timestamp”:ISODate(“2014-01-01T23:45:00.000Z”),“realPower”:604.5}
原因是您目前拥有的“子文档”结构不能很好地转换为服务器端聚合方法。这确实与将“部分数据”表示为“键”有关,这不是一个很好的模式

在某些情况下,可以使用表示时间间隔的“子文档”进行结构化,但通常需要将离散值的“bucket”保持在特定的时间间隔内,这里的要点是避免“嵌套数组”,这通常不利于更新

但在建议的表单中,您的查询只需应用。在特定的时间间隔内,可以使用以下选项来处理分组:

db.collection.aggregate([
//在日期之间匹配文档
{“$match”:{
“时间戳”:{“$gte”:开始日期,$lte:结束日期}
}},
//按小时分组
{“$组”:{
“_id”:{
“年”:{“$year”:“$timestamp”},
“月”:{“$month”:“$timestamp”},
“日”:{“$dayOfMonth”:“$timestamp”},
“小时”:{“$hour”:“$timestamp”}
},
“平均功率”:{“$avg”:“$realPower”}
}}
])
实际上,您从时间戳值中定义了一个“分组键”,对于结果中需要的其他值,您可以应用任意一个值,在本例中为平均值

或者,除了使用,您还可以将日期对象转换为历元时间戳值,并将日期数学应用于时间间隔。其中
epochDate
这里是一个日期对象,作为表示“1970-01-01”的参数传递,该参数是0个纪元日期:

db.collection.aggregate([
//在日期之间匹配文档
{“$match”:{
“时间戳”:{“$gte”:开始日期,$lte:结束日期}
}},
//按天分组:1000*60*60*24=一天中的毫秒
{“$组”:{
“_id”:{
“$subtract”:[
{“$subtract”:[
“$timestamp”,epochDate
]},
{“$mod”:[
{“$subtract”:[
“$timestamp”,epochDate
]},
1000 * 60 * 60 * 24
]}
]
},
“sumPower”:{“$sum”:“$realPower”}
}}
])
如果需要的话,可以将生成的时间戳值反馈到日期对象中。这里的诀窍是,从另一个日期对象中“减去”一个日期对象会导致以毫秒为单位的差值,以数字表示


然而,在当前的结构中,您需要一个JavaScript处理程序来在服务器端处理这个问题。由于需要“解释”代码,这将发生得慢得多

因此,在映射器中,每月为“总和”分组

function(){
var值=[];
var realPower=this.realPower;
for(在realPower中的var k){
对于(k中的变量i){
推送(realPower[k][i]);
}
}
散发(
{ 
“年”:this.timestamp.getFullYear(),
“月”:this.timestamp.getMonth()+1
},
{“值”:值}
);
}
然后是减速器:

函数(键、值){
变量结果={“值”:[]};
values.forEach(函数(值){
value.values.forEach(函数(项){
结果.值.推送(项目);
}
}
}
并在finalize函数中处理“sum”,以防针对给定分组仅发出一个单音键:

函数(键、值){
返回Array.sum(value.values);
}
并通过查询调用mapReduce:

results=db.collection.inline\u map\u reduce(
地图,
减少
查询={“时间戳”:{“$gte”:开始日期,$lte:结束日期},
定稿
)
因此,通常情况下会更难看,当然也会更慢。正如您在“映射器”定义中看到的,需要遍历“子文档”结构,或者选择“特定”键,例如每小时累积


在这两种情况下,服务器端处理通常是
[datetime.datetime(2014, 1, 1, 1, 0), 545.5]
[datetime.datetime(2014, 1, 1, 1, 15), 614.5]
[datetime.datetime(2014, 1, 1, 1, 30), 586.25]
[datetime.datetime(2014, 1, 1, 1, 45), 565.75]
(...)
[datetime.datetime(2014, 1, 1, 23, 45), 604.5]
def date_span(start_date, end_date, data):
    delta = datetime.timedelta(hours=15)
    current_date = start_date.replace(minute=0)
    while current_date < end_date:
        yield current_date
        current_date += delta