我们有一个Django,Postgresql数据库,其中包含以下对象:
object_date = models.DateTimeField()
作为一个领域。
我们需要每天按小时计算对象,因此我们需要删除一些额外的时间数据,例如:分钟,秒和微秒。
我们可以删除python中的额外时间数据:
query = MyModel.objects.values('object_date')
data = [tweet['tweet_date'].replace(minute=0, second=0, microsecond=0) for tweet in query
这给我们留下了一个包含日期和时间的列表。
我的问题:在查询本身中有更好,更快,更清晰的方法吗?
答案 0 :(得分:2)
count = len(MyModel.objects.filter(object_date__range=(beginning_of_hour, end_of_hour)))
或
count = MyModel.objects.filter(object_date__range=(beginning_of_hour, end_of_hour)).count()
假设我理解了您要求的内容,则返回具有特定时间范围内日期的对象数。将范围设置为从小时开始到小时结束,您将返回在该小时内创建的所有对象。可以使用Count()
或len()
,具体取决于所需的用途。有关详细信息,请查看https://docs.djangoproject.com/en/1.9/ref/models/querysets/#count
答案 1 :(得分:1)
如果您只想获取没有时间数据的日期,可以使用extra
来声明计算字段:
query = MyModel.objects
.extra(select={
'object_date_group': 'CAST(object_date AS DATE)',
'object_hour_group': 'EXTRACT(HOUR FROM object_date)'
})
.values('object_date_group', 'object_hour_group')
尽管如此,你并没有从中获得太多收益;数据库现在向您发送更多数据。
但是,使用这些附加字段,您可以使用聚合通过添加一行来立即获取您要查找的计数:
query = MyModel.objects
.extra(select={
'object_date_group': 'CAST(object_date AS DATE)',
'object_hour_group': 'EXTRACT(HOUR FROM object_date)'
})
.values('object_date_group', 'object_hour_group')
.annotate(count=Count('*'))
或者,您可以使用任何有效的SQL将我将两个字段组合成一个字段,例如将其格式化为字符串。这样做的好处是,您可以使用tuple
构建Counter
以便于查询(使用values_list()
)。
这个查询肯定比在Python中进行计数更有效。但是,对于可能不那么重要的后台工作。
一个缺点是这段代码不可移植;例如,它不适用于SQLite,您可能仍在使用它来进行测试。在这种情况下,您可以省去麻烦并立即编写raw
查询,这将是不可移植但更具可读性。
从1.10开始,由于添加了expressions,因此可以使用TruncHour
很好地执行此查询。以下是对解决方案外观的建议:
from collections import Counter
from django.db.models import Count
from django.db.models.functions import TruncHour
counts_by_group = Counter(dict(
MyModel.objects
.annotate(object_group=TruncHour('object_date'))
.values_list('object_group')
.annotate(count=Count('object_group'))
)) # query with counts_by_group[datetime.datetime(year, month, day, hour)]
优雅,高效,便携。 :)