时间戳Django中的TruncHour聚合

时间:2017-09-27 11:24:57

标签: django django-models orm django-orm

我有一个peoplecount和timestamp的数据,我希望以小时方式格式聚合.Peleclecount对象的模型如下所示:

class PeopleCount(models.Model):
    """
    A webapp model classs to store People Count Details.
    """
    timestamp = models.DateTimeField(auto_now=True)
    people_count_entry = models.IntegerField(blank=True, null=True)
    people_count_exit = models.IntegerField(blank=True, null=True)
    store = models.ForeignKey(Store, blank=True, null=True)
    profile = models.ForeignKey(Profile)
    camera = models.ForeignKey(Camera)
    recorded_time = models.DateTimeField(null=True, blank=True)

    def str(self):
        return "People Count {}".format(self.timestamp)

    class Meta:
        verbose_name = "People Count"
        verbose_name_plural = "People Count"
        ordering = ['-timestamp']

我正在使用以下查询以小时为基础获取数据:

queryset = PeopleCount.objects.filter(
                    **json.loads(
                        self.request.query_params['filter'])['object_params']
                ).annotate(
                    time_series=TruncHour('recorded_time')).values(
                    'time_series').annotate(
                    people_count_entry=Sum('people_count_entry')).values(
                    'time_series',
                    'people_count_entry').annotate(
                    people_count_exit=Sum('people_count_exit')).values(
                    'time_series', 'people_count_entry',
                    'people_count_exit')

上述查询的问题在于它实际上不会按小时聚合,而是为每个时间戳保留单独的值 我必须在客户端操纵。 客户端方法有效,但是对于更大的查询集需要花费大量时间。 希望我的问题陈述清楚。 谢谢。

1 个答案:

答案 0 :(得分:2)

阅读Aggregation - Interaction with default ordering or order_by()

  

在选择输出数据时,将使用在查询集的 order_by()部分中提及的字段(或在模型的默认排序中使用的字段),即使它们不是在 values()调用中指定。这些额外字段用于将“喜欢”结果组合在一起......

queryset = (
    PeopleCount.objects
    .filter(**json.loads(self.request.query_params['filter'])['object_params'])
    .order_by()    # THIS IS THE FIX - remove ordering by 'object_params'
    .annotate(time_series=TruncHour('recorded_time'))
    .values('time_series')  # output only this - to be grouped
    .annotate(
        people_count_entry=Sum('people_count_entry'),
        people_count_exit=Sum('people_count_exit'),
    )
    # no need to add or remove fields by .values()
    .order_by('time_series')  # order by truncated not by individual !!!
)
# print(str(queryset.query))  # SQL check is perfect for debugging