From c440246bb687ea78a7d3b530a3f956c19b1e2b3a Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Mon, 19 Sep 2016 13:10:49 +0200
Subject: [PATCH] Faster Search endpoint (less DB queries)

---
 funkwhale_api/music/views.py | 41 ++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/funkwhale_api/music/views.py b/funkwhale_api/music/views.py
index 8a4dfcd..6c5b38d 100644
--- a/funkwhale_api/music/views.py
+++ b/funkwhale_api/music/views.py
@@ -39,7 +39,12 @@ class TagViewSetMixin(object):
         return queryset
 
 class ArtistViewSet(SearchMixin, viewsets.ReadOnlyModelViewSet):
-    queryset = models.Artist.objects.all().order_by('-creation_date').prefetch_related('albums__tracks__files', 'albums__tracks__tags')
+    queryset = (
+        models.Artist.objects.all()
+                             .order_by('-creation_date')
+                             .prefetch_related(
+                                'albums__tracks__files',
+                                'albums__tracks__tags'))
     serializer_class = serializers.ArtistSerializerNested
     permission_classes = [ConditionalAuthentication]
     search_fields = ['name']
@@ -111,17 +116,45 @@ class Search(views.APIView):
     def get_tracks(self, query):
         search_fields = ['mbid', 'title', 'album__title', 'artist__name']
         query_obj = utils.get_query(query, search_fields)
-        return models.Track.objects.all().filter(query_obj)[:self.max_results]
+        return (
+            models.Track.objects.all()
+                        .filter(query_obj)
+                        .select_related('album__artist')
+                        .prefetch_related(
+                            'tags',
+                            'artist__albums__tracks__tags',
+                            'files')
+        )[:self.max_results]
+
 
     def get_albums(self, query):
         search_fields = ['mbid', 'title', 'artist__name']
         query_obj = utils.get_query(query, search_fields)
-        return models.Album.objects.all().filter(query_obj)[:self.max_results]
+        return (
+            models.Album.objects.all()
+                        .filter(query_obj)
+                        .select_related()
+                        .prefetch_related(
+                            'tracks__tags',
+                            'tracks__files',
+                            )
+        )[:self.max_results]
+
 
     def get_artists(self, query):
         search_fields = ['mbid', 'name']
         query_obj = utils.get_query(query, search_fields)
-        return models.Artist.objects.all().filter(query_obj)[:self.max_results]
+        return (
+            models.Artist.objects.all()
+                         .filter(query_obj)
+                         .select_related()
+                         .prefetch_related(
+                             'albums__tracks__tags',
+                             'albums__tracks__files',
+                             )
+
+        )[:self.max_results]
+
 
     def get_tags(self, query):
         search_fields = ['slug', 'name']
-- 
GitLab