optimized recipe search query annotation performance

This commit is contained in:
vabene1111
2022-09-16 13:24:57 +02:00
parent e06c82297d
commit 845408244b
2 changed files with 12 additions and 26 deletions

View File

@ -115,6 +115,10 @@ class RecipeSearch():
def get_queryset(self, queryset): def get_queryset(self, queryset):
self._queryset = queryset self._queryset = queryset
self._queryset = self._queryset.prefetch_related('keywords')
self._queryset = self._queryset.annotate(rating=Avg('cooklog__rating'))
self._queryset = self._queryset.annotate(last_cooked=Max('cooklog__created_at'))
self._build_sort_order() self._build_sort_order()
self._recently_viewed(num_recent=self._num_recent) self._recently_viewed(num_recent=self._num_recent)
self._cooked_on_filter(cooked_date=self._cookedon) self._cooked_on_filter(cooked_date=self._cookedon)

View File

@ -684,25 +684,6 @@ class NutritionInformationSerializer(serializers.ModelSerializer):
class RecipeBaseSerializer(WritableNestedModelSerializer): class RecipeBaseSerializer(WritableNestedModelSerializer):
def get_recipe_rating(self, obj):
try:
rating = obj.cooklog_set.filter(created_by=self.context['request'].user, rating__gt=0).aggregate(
Avg('rating'))
if rating['rating__avg']:
return rating['rating__avg']
except TypeError:
pass
return 0
def get_recipe_last_cooked(self, obj):
try:
last = obj.cooklog_set.filter(created_by=self.context['request'].user).order_by('created_at').last()
if last:
return last.created_at
except TypeError:
pass
return None
# TODO make days of new recipe a setting # TODO make days of new recipe a setting
def is_recipe_new(self, obj): def is_recipe_new(self, obj):
if getattr(obj, 'new_recipe', None) or obj.created_at > (timezone.now() - timedelta(days=7)): if getattr(obj, 'new_recipe', None) or obj.created_at > (timezone.now() - timedelta(days=7)):
@ -712,12 +693,13 @@ class RecipeBaseSerializer(WritableNestedModelSerializer):
class RecipeOverviewSerializer(RecipeBaseSerializer): class RecipeOverviewSerializer(RecipeBaseSerializer):
keywords = KeywordLabelSerializer(many=True) # keywords = KeywordLabelSerializer(many=True)
rating = serializers.SerializerMethodField('get_recipe_rating')
last_cooked = serializers.SerializerMethodField('get_recipe_last_cooked')
new = serializers.SerializerMethodField('is_recipe_new') new = serializers.SerializerMethodField('is_recipe_new')
recent = serializers.ReadOnlyField() recent = serializers.ReadOnlyField()
rating = CustomDecimalField()
last_cooked = serializers.DateTimeField()
def create(self, validated_data): def create(self, validated_data):
pass pass
@ -727,7 +709,7 @@ class RecipeOverviewSerializer(RecipeBaseSerializer):
class Meta: class Meta:
model = Recipe model = Recipe
fields = ( fields = (
'id', 'name', 'description', 'image', 'keywords', 'working_time', 'id', 'name', 'description', 'image', 'keywords', 'working_time',
'waiting_time', 'created_by', 'created_at', 'updated_at', 'waiting_time', 'created_by', 'created_at', 'updated_at',
'internal', 'servings', 'servings_text', 'rating', 'last_cooked', 'new', 'recent' 'internal', 'servings', 'servings_text', 'rating', 'last_cooked', 'new', 'recent'
) )
@ -737,10 +719,10 @@ class RecipeOverviewSerializer(RecipeBaseSerializer):
class RecipeSerializer(RecipeBaseSerializer): class RecipeSerializer(RecipeBaseSerializer):
nutrition = NutritionInformationSerializer(allow_null=True, required=False) nutrition = NutritionInformationSerializer(allow_null=True, required=False)
steps = StepSerializer(many=True) steps = StepSerializer(many=True)
keywords = KeywordSerializer(many=True) #keywords = KeywordSerializer(many=True)
rating = serializers.SerializerMethodField('get_recipe_rating')
last_cooked = serializers.SerializerMethodField('get_recipe_last_cooked')
shared = UserSerializer(many=True, required=False) shared = UserSerializer(many=True, required=False)
rating = CustomDecimalField()
last_cooked = serializers.DateTimeField()
class Meta: class Meta:
model = Recipe model = Recipe