Return 按小时聚合时的日期对象
Return Date Object when Aggregating by Hour
我正在尝试通过将日期时间减少到小时来汇总记录。有没有办法在 mongoengine 中完成并保存字段类型?
我的数据是:
{'spent': 7, 'time_started': datetime.datetime(2015, 4, 21, 16, 2, 16, 661000)}
{'spent': 3, 'time_started': datetime.datetime(2015, 4, 21, 17, 8, 5, 415000)}
{'spent': 3, 'time_started': datetime.datetime(2015, 4, 21, 15, 52, 45, 917000)}
{'spent': 1, 'time_started': datetime.datetime(2015, 4, 21, 16, 42, 32, 313000)}
{'spent': 8, 'time_started': datetime.datetime(2015, 4, 21, 16, 35, 46, 863000)}
{'spent': 5, 'time_started': datetime.datetime(2015, 4, 21, 15, 55, 1, 217000)}
{'spent': 10, 'time_started': datetime.datetime(2015, 4, 20, 17, 41, 50, 5000)}
这是我到目前为止得出的结论:
pipeline =[
'match': {
"time_started": {
"$gte": datetime.datetime(2015, 4, 21, 0, 0, 0),
}
},
'project': {
"spent": "$spent",
"time_started": {"$dateToString": {
"format": "%Y-%m-%dT%H:00:00",
"date": "$time_started"
}}
},
'group': {
"_id": {
"time_started": "$time_started",
},
"spent_total": {"$sum": "$spent"}
}
]
它运行良好,但 "time_started" 是结果中的一个字符串,而我需要日期时间,如下所示:
{'spent_total': 16, 'time_started': datetime.datetime(2015, 4, 21, 16, 0, 0)}
{'spent_total': 3, 'time_started': datetime.datetime(2015, 4, 21, 17, 0, 0)}
{'spent_total': 8, 'time_started': datetime.datetime(2015, 4, 21, 15, 0, 0)}
是的。您可以将 "date math" 与 object 一起使用,然后它们将保留为 BSON 日期类型并转换为 driver:
中的本机类型
pipeline = [
{ '$match': {
"time_started": {
"$gte": datetime.datetime(2015, 4, 21, 0, 0, 0),
}
}
}},
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [
"$time_started", datetime.datetime(1970, 1, 1)
]},
{ "$mod": [
{ "$subtract": [
"$time_started", datetime.datetime(1970, 1, 1)
]},
1000 * 60 * 60
]}
]},
datetime.datetime(1970, 1, 1)
]
},
"spent_total": { "$sum": "$spent" }
}}
];
Class._get_collection().aggregate(pipeline);
基本概念是,当您从日期字段的值中减去 "epoch date" 时,返回的值为数字。在这里,您应用模数 $mod
计算一小时内毫秒数的余数,并将日期四舍五入到小时。
那么当你 "add" 将 "epoch date" 转换为数字时,情况正好相反,那么它 returns 一个新的 Date
object 等于所代表的以毫秒为单位的值。
因为它已经只是一个日期,所以 driver 会相应地处理它,不需要翻译。比使用字符串或其他运算符要好得多。另请注意,您不需要 $project
,只需将此类转换直接应用于 $group
中的 _id
,这甚至可以加快速度。
我正在尝试通过将日期时间减少到小时来汇总记录。有没有办法在 mongoengine 中完成并保存字段类型?
我的数据是:
{'spent': 7, 'time_started': datetime.datetime(2015, 4, 21, 16, 2, 16, 661000)}
{'spent': 3, 'time_started': datetime.datetime(2015, 4, 21, 17, 8, 5, 415000)}
{'spent': 3, 'time_started': datetime.datetime(2015, 4, 21, 15, 52, 45, 917000)}
{'spent': 1, 'time_started': datetime.datetime(2015, 4, 21, 16, 42, 32, 313000)}
{'spent': 8, 'time_started': datetime.datetime(2015, 4, 21, 16, 35, 46, 863000)}
{'spent': 5, 'time_started': datetime.datetime(2015, 4, 21, 15, 55, 1, 217000)}
{'spent': 10, 'time_started': datetime.datetime(2015, 4, 20, 17, 41, 50, 5000)}
这是我到目前为止得出的结论:
pipeline =[
'match': {
"time_started": {
"$gte": datetime.datetime(2015, 4, 21, 0, 0, 0),
}
},
'project': {
"spent": "$spent",
"time_started": {"$dateToString": {
"format": "%Y-%m-%dT%H:00:00",
"date": "$time_started"
}}
},
'group': {
"_id": {
"time_started": "$time_started",
},
"spent_total": {"$sum": "$spent"}
}
]
它运行良好,但 "time_started" 是结果中的一个字符串,而我需要日期时间,如下所示:
{'spent_total': 16, 'time_started': datetime.datetime(2015, 4, 21, 16, 0, 0)}
{'spent_total': 3, 'time_started': datetime.datetime(2015, 4, 21, 17, 0, 0)}
{'spent_total': 8, 'time_started': datetime.datetime(2015, 4, 21, 15, 0, 0)}
是的。您可以将 "date math" 与 object 一起使用,然后它们将保留为 BSON 日期类型并转换为 driver:
中的本机类型pipeline = [
{ '$match': {
"time_started": {
"$gte": datetime.datetime(2015, 4, 21, 0, 0, 0),
}
}
}},
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [
"$time_started", datetime.datetime(1970, 1, 1)
]},
{ "$mod": [
{ "$subtract": [
"$time_started", datetime.datetime(1970, 1, 1)
]},
1000 * 60 * 60
]}
]},
datetime.datetime(1970, 1, 1)
]
},
"spent_total": { "$sum": "$spent" }
}}
];
Class._get_collection().aggregate(pipeline);
基本概念是,当您从日期字段的值中减去 "epoch date" 时,返回的值为数字。在这里,您应用模数 $mod
计算一小时内毫秒数的余数,并将日期四舍五入到小时。
那么当你 "add" 将 "epoch date" 转换为数字时,情况正好相反,那么它 returns 一个新的 Date
object 等于所代表的以毫秒为单位的值。
因为它已经只是一个日期,所以 driver 会相应地处理它,不需要翻译。比使用字符串或其他运算符要好得多。另请注意,您不需要 $project
,只需将此类转换直接应用于 $group
中的 _id
,这甚至可以加快速度。