diff --git a/akarpov/music/documents.py b/akarpov/music/documents.py index 39d26be..02c46e9 100644 --- a/akarpov/music/documents.py +++ b/akarpov/music/documents.py @@ -35,7 +35,8 @@ class SongDocument(Document): name = fields.TextField( attr="name", fields={ - "raw": fields.KeywordField(normalizer="lowercase"), + "raw": fields.KeywordField(), + "exact": fields.KeywordField(normalizer="lowercase"), }, ) suggest = fields.CompletionField() diff --git a/akarpov/music/services/search.py b/akarpov/music/services/search.py index 74e66b8..b642d46 100644 --- a/akarpov/music/services/search.py +++ b/akarpov/music/services/search.py @@ -12,8 +12,11 @@ def search_song(query): search_query = ES_Q( "bool", should=[ - ES_Q("match", name=query), - ES_Q("match", name__russian=query), + ES_Q("match_phrase", name__exact=query, boost=3), # Boost for exact matches + ES_Q( + "match_phrase", name__raw=query.lower(), boost=2.5 + ), # Case-insensitive exact match + ES_Q("match", name__russian=query), # Match in Russian field ES_Q( "multi_match", query=query, @@ -24,7 +27,7 @@ def search_song(query): "authors.name.raw^3", "album.name^3", "album.name.raw^3", - "name.raw^2", + "meta.*", ], type="best_fields", fuzziness="AUTO", @@ -38,8 +41,8 @@ def search_song(query): fields=["authors.name", "authors.name.raw"], fuzziness="AUTO", ), + boost=2, ), - ES_Q("wildcard", name__raw=f"*{query.lower()}*"), ES_Q( "nested", path="album", @@ -49,13 +52,14 @@ def search_song(query): fields=["album.name", "album.name.raw"], fuzziness="AUTO", ), + boost=2, ), ES_Q( - "nested", - path="album", - query=ES_Q("wildcard", album__name__raw=f"*{query.lower()}*"), - ), - ES_Q("wildcard", meta__raw=f"*{query.lower()}*"), + "wildcard", name__raw=f"*{query.lower()}*" + ), # Wildcard search for partial matches + ES_Q( + "wildcard", meta__raw=f"*{query.lower()}*" + ), # Wildcard search in meta fields ], minimum_should_match=1, )