Django комментирует подсчет сложных подзапросов - PullRequest
0 голосов
/ 01 ноября 2019

У меня есть следующая модель:

class Visit(models.Model):
   ...
   device_id = models.CharField(...)
   created_at = models.DateTimeField(auto_now_add=True)
   ...

Эта модель в основном обозначает посещение какого-либо места, device_id однозначно идентифицирует человека, и один и тот же человек может посещать это место несколько раз, следовательно, создавая несколько записей в этомТаблица.

Я строю аналитические методы поверх этой модели. Одна вещь, которую я хочу сделать, это показать за последние 30 дней количество людей, которые посетили только один раз в течение этого дня. Основываясь на базовом подходе, я могу выдавать запрос БД для каждого дня, например, так:

for date in dates:
    start_time = date
    end_time = date + datetime.timedelta(days=1)

    Visitor.objects.filter(
        site__in=node_descendants,
        created_at__gte=start_date,
        created_at__lt=end_date)
    ).values('device_id').annotate(visit_count=Count('device_id')).filter(visit_count=1).count()

Теперь я хочу вычислять данные для каждого дня в диапазоне 30 дней с помощью одного запроса, используя подзапрос, напримерthis:

single_visitor_query = Visitor.objects.filter(
    created_at__date=OuterRef('truncated_date')
).order_by().values('device_id')
 .annotate(visit_count=Count('device_id')).filter(visit_count=1)
 .annotate(count=Count('*')).values('count')

chart_data_query = Visitor.objects.filter(
    created_at__gte=start_date,  # Start of month
    created_at__lt=end_date,  # End of month
).annotate(
    truncated_date=TruncDay('created_at')
).values('truncated_date').distinct().annotate(
    single_visitor_count=Subquery(single_visitor_query[:1], output_field=PositiveIntegerField()
)

У меня есть пара проблем с этим подходом:

  • количество, полученное в результате подзапроса, не является числом всех элементов, имеющих visit_count = 1, но онивсе 1. Я знаю, что подзапрос несколько отключен, но я не могу понять, как исправить его, чтобы он возвращал счетчик для всех элементов, проходящих фильтр.
  • Я бы хотел, чтобы подзапрос выполнялся для каждого truncated_date (30раз в этом случае), но кажется, что он работает для каждого экземпляра, который проходит начальный фильтр. Я проверил полученный SQL-запрос, и он не группируется по " truncated_date ". Любые идеи, почему это может иметь место?
...