diff --git a/akarpov/music/documents.py b/akarpov/music/documents.py index b0a4efd..39d26be 100644 --- a/akarpov/music/documents.py +++ b/akarpov/music/documents.py @@ -38,6 +38,7 @@ class SongDocument(Document): "raw": fields.KeywordField(normalizer="lowercase"), }, ) + suggest = fields.CompletionField() meta = fields.ObjectField(dynamic=True) diff --git a/akarpov/music/services/search.py b/akarpov/music/services/search.py index ad2f417..97a7e80 100644 --- a/akarpov/music/services/search.py +++ b/akarpov/music/services/search.py @@ -1,4 +1,6 @@ +from django.core.cache import cache from django.db.models import Case, When +from django_elasticsearch_dsl.registries import registry from elasticsearch_dsl import Q as ES_Q from akarpov.music.documents import SongDocument @@ -10,12 +12,20 @@ def search_song(query): search_query = ES_Q( "bool", should=[ + ES_Q("match", name=query), + ES_Q("match", name__russian=query), ES_Q( "multi_match", query=query, fields=["name^5", "authors.name^3", "album.name^3"], + type="best_fields", fuzziness="AUTO", ), + ES_Q( + "nested", + path="authors", + query=ES_Q("match", authors__name=query), + ), ES_Q("wildcard", name__raw=f"*{query.lower()}*"), ES_Q( "nested", @@ -32,11 +42,9 @@ def search_song(query): minimum_should_match=1, ) - search = search.query(search_query) - + search = search.query(search_query).size(20) response = search.execute() - # Check for hits and get song instances if response.hits: hit_ids = [hit.meta.id for hit in response.hits] songs = Song.objects.filter(id__in=hit_ids).order_by( @@ -46,3 +54,24 @@ def search_song(query): return songs return Song.objects.none() + + +def autocomplete_search(query): + s = SongDocument.search() + s = s.suggest("song_suggest", query, completion={"field": "suggest"}) + suggestions = s.execute().suggest.song_suggest[0].options + return [option.text for option in suggestions] + + +def get_popular_songs(): + if "popular_songs" in cache: + return cache.get("popular_songs") + else: + songs = Song.objects.filter(played__gt=300).order_by("-played")[:10] + cache.set("popular_songs", songs, timeout=3600) + return songs + + +def bulk_update_index(model_class): + qs = model_class.objects.all() + registry.update(qs, bulk_size=100)