Поиск поля документации не очень помогает в моем случае
Как выглядит мой запрос сейчас
date_delta = 2
queryset = TrendData.objects.filter(owner__trend_type__mnemonic='posts',
date_trend__date__range=[date_from, date_to]).values('owner_id', 'owner__name')
queryset.annotate(owner_name=F('owner_id__name')).values('owner_name', 'owner_id').annotate(
views = Sum(Case(When(owner_id__gt=1, then=F('views') / date_delta)), default=('views')...,
output_field=IntegerField() )
)
вывод queryset
выглядит следующим образом:
{'owner_id': 1306, 'owner__name': 'Some name123'},
{'owner_id': 1307, 'owner__name': 'Somename as well'},
{'owner_id': 1308, 'owner__name': 'aand another name'},
{'owner_id': 1306, 'owner__name': 'Some name123'}
Как вы можете видеть, есть совпадающие идентификаторы owner_id, и набор запросов len () равен 100 000 в день, поэтому, если диапазон дат составляет 5 дней, набор запросов len () == 500 000.мой models.py выглядит следующим образом
class Owner(models.Model):
class Meta:
verbose_name_plural = 'Objects'
TREND_OWNERS = Choices('group', 'user')
link = models.CharField(max_length=255)
name = models.CharField(max_length=255)
owner_type = models.CharField(choices=TREND_OWNERS, max_length=50)
trend_type = models.ForeignKey(TrendType, on_delete=models.CASCADE)
def __str__(self):
return f'{self.link}[{self.trend_type}]'
class TrendData(models.Model):
class Meta:
verbose_name_plural = 'Trends'
owner = models.ForeignKey(Owner, on_delete=models.CASCADE)
views = models.IntegerField()
views_u = models.IntegerField()
likes = models.IntegerField()
shares = models.IntegerField()
interaction_rate = models.DecimalField(max_digits=20, decimal_places=10)
mean_age = models.IntegerField()
date_trend = models.DateTimeField()
Я понял, что он будет работать нормально, но это будет неправильно, поскольку, если owner_id велик, он будет делиться на date_delta, где в моем случае я хочу, если owner_id произойдетв запросе более одного раза.Я пробовал owner_id__count__gt
, но этого не существует: (
Я хотел бы знать, есть ли способ подсчета вхождений owner_id в моем аннотированном наборе запросов Case(When())
. Это в буквальном смысле решит мою проблему. Если оно большечем 1, чем мы делим на date_delta, иначе мы оставляем все как есть
Обновление:
Просто чтобы прояснить, эта аннотация делает отличную работу, однако она такжеделит некоторые запросы, которые я не хочу делить (в моем случае NON дубликат набора запросов owner_id по-прежнему делит его представления, общие ресурсы и т.д. на 2), поэтому я использую Case (When ()), упомянутый выше
queryset.values('owner__name', 'owner_id').annotate(
views=Sum('views') / 2,
views_u=Sum('views_u') / 2,
likes=Sum('likes') / 2,
shares=Sum('shares') / 2,
interaction_rate=Sum('interaction_rate') / 2,
mean_age=Sum('mean_age') / 2)
ОБНОВЛЕНИЕ # 2 Это моя логика, но в python
json_output = []
for item in (queryset
.values('owner__name', 'owner_id')
.annotate(owner_count=Count('owner_id'))
.annotate(views=Sum('views'), views_u=Sum('views_u'),
likes=Sum('likes'),
shares=Sum('shares'),
interaction_rate=Sum('interaction_rate'),
mean_age=Sum('mean_age')):
if item['owner_count'] > 1:
item['views'] = item['views'] / date_delta
item['views_u'] = item['views_u'] / date_delta
item['likes'] = item['likes'] / date_delta
item['shares'] = item['shares'] / date_delta
item['interaction_rate'] = '{:.10f}'.format(
Decimal(item['interaction_rate']) / date_delta)
item['mean_age'] = item['mean_age'] / date_delta
json_output.append(item)
else:
json_output.append(item)