Как я могу объединить строки с помощью конкатената в Django annotate?
У меня есть следующая модель в Django:
class Click(models.Model):
url = models.ForeignKey(Url, on_delete=models.CASCADE)
browser = models.CharField(max_length=255)
platform = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Я хочу построить запрос, чтобы получить общее количество кликов в день в текущем месяце, а также браузеры и платформы в конкатенированном виде. Например:
[
{
'created_at__day': 28,
'browsers': 'Chrome, Firefox',
'platforms': 'Windows, Linux',
'clicks': 4
}
]
Что я делал до этого момента, так это запрос:
queryset = Click.objects.filter(
url=url_instance,
created_at__month=datetime.now().month
).values('created_at__day', 'browser').annotate(
clicks=Count('created_at'),
)
Как я могу объединить все браузеры и платформы, группируя только по created_at__day?
Неясно, какие именно данные у вас есть, чтобы получить желаемый результат, но если вы используете Postgresql в качестве базы данных, StringAgg или ArrayAgg могут быть тем, что вы ищете.
Если вы хотите исключить дубликаты из ваших агрегированных строк, это становится немного сложнее.
Я думаю, что вы близки, как упомянул @Shabble, StringAgg
если вы используете Postresql:
queryset = Click.objects.filter(
url=url_instance,
created_at__month=datetime.now().month
).values('created_at__day', 'browser').annotate(
clicks=Count('created_at'),
platforms=StringAgg('platform', delimiter=', ', distinct=True),
)
Если нет, вам придется использовать Subquery
, и написать соответствующую строку Aggregation
для базы данных. Получилось бы что-то вроде:
# Inner query
click_platforms = Click.objects.filter(
url=url_instance,
created_at__month=datetime.now().month,
created_at__day=OuterRef("created_at__day")
).distinct()
# Outer query
queryset = Click.objects.filter(
url=url_instance,
created_at__month=datetime.now().month
).values('created_at__day', 'browser').annotate(
clicks=Count('created_at'),
platforms=YourAggregation(click_platforms),
)
Я не могу написать YourAggregation
, это зависит от того, что доступно в вашей базе данных.