From 89f6e3656bcb569916f9d058b0d01dbf4ae5d9f5 Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Thu, 3 Jan 2019 17:34:14 +0100
Subject: [PATCH] Show short entries first in search results to improve UX

---
 api/funkwhale_api/common/utils.py           | 10 +++++++++-
 api/funkwhale_api/music/views.py            | 17 +++++++++--------
 changes/changelog.d/searchorder.enhancement |  1 +
 3 files changed, 19 insertions(+), 9 deletions(-)
 create mode 100644 changes/changelog.d/searchorder.enhancement

diff --git a/api/funkwhale_api/common/utils.py b/api/funkwhale_api/common/utils.py
index 81bc5c026..bd9fd87c5 100644
--- a/api/funkwhale_api/common/utils.py
+++ b/api/funkwhale_api/common/utils.py
@@ -9,7 +9,7 @@ from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit
 
 from django.conf import settings
 from django import urls
-from django.db import transaction
+from django.db import models, transaction
 
 
 def rename_file(instance, field_name, new_name, allow_missing_file=False):
@@ -139,3 +139,11 @@ def parse_meta(html):
     meta = [elem for elem in tree.iter() if elem.tag in ["meta", "link"]]
 
     return [dict([("tag", elem.tag)] + list(elem.items())) for elem in meta]
+
+
+def order_for_search(qs, field):
+    """
+    When searching, it's often more useful to have short results first,
+    this function will order the given qs based on the length of the given field
+    """
+    return qs.annotate(__size=models.functions.Length(field)).order_by("__size")
diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py
index 1fcd782fb..ba4ffd1f0 100644
--- a/api/funkwhale_api/music/views.py
+++ b/api/funkwhale_api/music/views.py
@@ -448,28 +448,29 @@ class Search(views.APIView):
             "artist__name__unaccent",
         ]
         query_obj = utils.get_query(query, search_fields)
-        return (
+        qs = (
             models.Track.objects.all()
             .filter(query_obj)
             .select_related("artist", "album__artist")
-        )[: self.max_results]
+        )
+        return common_utils.order_for_search(qs, "title")[: self.max_results]
 
     def get_albums(self, query):
         search_fields = ["mbid", "title__unaccent", "artist__name__unaccent"]
         query_obj = utils.get_query(query, search_fields)
-        return (
+        qs = (
             models.Album.objects.all()
             .filter(query_obj)
             .select_related()
-            .prefetch_related("tracks")
-        )[: self.max_results]
+            .prefetch_related("tracks__artist")
+        )
+        return common_utils.order_for_search(qs, "title")[: self.max_results]
 
     def get_artists(self, query):
         search_fields = ["mbid", "name__unaccent"]
         query_obj = utils.get_query(query, search_fields)
-        return (models.Artist.objects.all().filter(query_obj).with_albums())[
-            : self.max_results
-        ]
+        qs = models.Artist.objects.all().filter(query_obj).with_albums()
+        return common_utils.order_for_search(qs, "name")[: self.max_results]
 
     def get_tags(self, query):
         search_fields = ["slug", "name__unaccent"]
diff --git a/changes/changelog.d/searchorder.enhancement b/changes/changelog.d/searchorder.enhancement
new file mode 100644
index 000000000..b180006a3
--- /dev/null
+++ b/changes/changelog.d/searchorder.enhancement
@@ -0,0 +1 @@
+Show short entries first in search results to improve UX
-- 
GitLab