Django JSONField Aggregate и Sum
У меня есть следующий JSON, сохраненный в БД PostgreSQL 9.4 и работающий под управлением Django 2.2
[{"rating": 6, "companyvalue_id": 188, "team_members_name": "pidofod tester", "users_teammember_id": 2793}, {"rating": 7, "companyvalue_id": 207, "team_members_name": "pidofod tester", "users_teammember_id": 2793}, {"rating": 4, "companyvalue_id": 207, "team_members_name": "xakir tester", "users_teammember_id": 2795}]
Имеется много записей в базе данных.
Я хотел бы объединить все экземпляры team_members_name
и Sum, чтобы узнать общую сумму rating
.
Данные JSON сохраняются в поле модели data = JSONField(null=True, blank=True)
Ближайший, который у меня есть -
def data_rating(self):
model = apps.get_model('model', 'ModelName')
model_count = model.objects.all()
return model_count.objects.annotate(
rating=Cast(
KeyTextTransform("rating", "data"),
IntegerField(),
)
).values("rating").distinct().aggregate(Sum("rating"))["rating__sum"]
Вышеописанное работает только для одного объекта JSON, т.е. {"rating": 6, "companyvalue_id": 188, "team_members_name": "pidofod tester", "users_teammember_id": 2793}
, однако мне нужно, чтобы KeyTextTransform
работал для многих объектов JSON и во многих строках базы данных.
Мне также нужно фильтровать/агрегировать каждого пользователя, т.е. что такое "team_members_name": "pidofod tester"
total rating
Sum.
Конечным результатом является возврат этого результата в конечную точку DRF.
Пробовал много вариантов, как показано ниже, но ни один не работает или кажется близким, чувствую, что может потребоваться переделка модели. Любые идеи и предложения приветствуются!
#return rating_tool_count.annotate(numbers_len=Func(F('rating_tool_data'), function='jsonb_array_length')).aggregate(rating_total=Sum(F("rating")))
#return rating_tool_count.annotate(single_nested_value=F("rating_tool_data__team_members_name"),array_access=F("rating_tool_data__rating"),)
#return rating_tool.objects.aggregate(Sum('rating_tool_data__rating')) #.values('rating_tool_data__rating').annotate(rating_total=Sum(Cast(KeyTextTransform("rating", "rating_tool_data"), models.IntegerField())))
#return rating_tool_count.annotate(team_members_name=Cast(KeyTextTransform(
#"team_members_name", "rating_tool_data"), models.TextField())).values("rating_tool_data").annotate(rating_total=Sum(Cast(KeyTextTransform("rating", "rating_tool_data"),
#models.IntegerField())),).order_by("-rating_total")
#return rating_tool_count.filter(rating_tool_data__name="pidofod tester").count()
#return rating_tool_count.aggregate(Sum('rating_tool_data__rating'))
#return rating_tool_count.aggregate(rating=Sum(Cast(KeyTextTransform("rating", "rating_tool_data"), models.IntegerField())))
# return rating_tool_count.values('rating_tool_data__rating').annotate(rating_total=Sum('rating_tool_data__rating')).order_by('-rating_tool_data__rating')
# return rating_tool_count.annotate(team_members_name=Cast(KeyTextTransform("team_members_name", "rating_tool_data"), models.TextField())).values("team_members_name").annotate(rating=Count("rating_tool_data"),ratings=Sum(Cast(KeyTextTransform("rating", "rating_tool_data"), models.IntegerField()))).order_by("-rating")
Попробуйте postgresql jsonb вместо json
jsonb позволяет эффективно извлекать значения в sql-запросах https://www.postgresql.org/docs/current/functions-json.html
также https://pganalyze.com/blog/postgres-jsonb-django-python может быть полезен