У меня есть модель обзора, которая находится во взаимосвязи один к одному с моделью оценки. Пользователь может выставить оценку по шести различным критериям - чистота, коммуникация, check_in, точность, местоположение и значение - которые определены как поля в модели оценки.
class Rating(models.Model):
cleanliness = models.PositiveIntegerField()
communication = models.PositiveIntegerField()
check_in = models.PositiveIntegerField()
accuracy = models.PositiveIntegerField()
location = models.PositiveIntegerField()
value = models.PositiveIntegerField()
class Review(models.Model):
room = models.ForeignKey('room.Room', on_delete=models.SET_NULL, null=True)
host = models.ForeignKey('user.User', on_delete=models.CASCADE, related_name='host_reviews')
guest = models.ForeignKey('user.User', on_delete=models.CASCADE, related_name='guest_reviews')
rating = models.OneToOneField('Rating', on_delete=models.SET_NULL, null=True)
content = models.CharField(max_length=2000)
Я думаю о способе расчета общей оценки, которая была бы средним значением для каждого столбца в модели рейтинга. Одним из способов может быть использование функции aggregate () Django, а другим вариантом может быть предварительная выборка всех обзоров и циклическое прохождение каждого обзора для ручного расчета общей оценки. Например,
for room in Room.objects.all()
ratings_dict = Review.objects.filter(room=room)\
.aggregate(*[Avg(field) for field in ['rating__cleanliness', 'rating__communication', \
'rating__check_in', 'rating__accuracy', 'rating__location', 'rating__value']])
ratings_sum = 0
for key in ratings_dict.keys():
ratings_sum += ratings_dict[key] if ratings_dict[key] else 0
Или, просто перебирая,
rooms = Room.objects.prefetch_related('review_set')
for room in rooms:
reviews = room.review_set.all()
ratings = 0
for review in reviews:
ratings += (review.rating.cleanliness + review.rating.communication + review.rating.check_in +
review.rating.accuracy + review.rating.location+ review.rating.value)/6
Какой способ будет более эффективным с точки зрения временной сложности и приведет к меньшему количеству обращений к БД?
Создает ли агрегат (Avg ('field_name')) один запрос Avg на уровне базы данных для каждого вызова функции?
Будет ли сначала вызов всех комнат с помощью prefetch_related () помочь уменьшить количество запросов позже при вызове room.review_set. все ()?