updated search

This commit is contained in:
Alexander Karpov 2024-12-05 16:36:50 +03:00
parent 600c903a68
commit f4ca7db696
3 changed files with 44 additions and 99 deletions

View File

@ -88,8 +88,12 @@ def get_liked(self, obj):
@extend_schema_field(ListAlbumSerializer) @extend_schema_field(ListAlbumSerializer)
def get_album(self, obj): def get_album(self, obj):
if obj.album: if obj.album_id:
return ListAlbumSerializer(Album.objects.cache().get(id=obj.album_id)).data try:
album = Album.objects.cache().get(id=obj.album_id)
return ListAlbumSerializer(album).data
except Album.DoesNotExist:
return None
return None return None
@extend_schema_field(ListAuthorSerializer(many=True)) @extend_schema_field(ListAuthorSerializer(many=True))
@ -105,16 +109,17 @@ def get_image(self, obj):
img = None img = None
if obj.image_cropped: if obj.image_cropped:
img = obj.image_cropped img = obj.image_cropped
else: elif obj.album_id:
album = Album.objects.cache().get(id=obj.album_id) try:
if album.image_cropped: album = Album.objects.cache().get(id=obj.album_id)
img = album.image_cropped if album.image_cropped:
else: img = album.image_cropped
authors = Author.objects.cache().filter( except Album.DoesNotExist:
Q(songs__id=obj.id) & ~Q(image="") pass
) if not img:
if authors: authors = Author.objects.cache().filter(Q(songs__id=obj.id) & ~Q(image=""))
img = authors.first().image_cropped if authors.exists():
img = authors.first().image_cropped
if img: if img:
return self.context["request"].build_absolute_uri(img.url) return self.context["request"].build_absolute_uri(img.url)
return None return None

View File

@ -48,7 +48,7 @@ class SongDocument(Document):
attr="name", attr="name",
fields={ fields={
"raw": fields.KeywordField(), "raw": fields.KeywordField(),
"exact": fields.KeywordField(normalizer="lowercase"), "exact": fields.KeywordField(normalizer="lowercase_normalizer"),
}, },
) )
name_transliterated = fields.TextField( name_transliterated = fields.TextField(
@ -67,6 +67,13 @@ class Index:
settings = { settings = {
"number_of_shards": 1, "number_of_shards": 1,
"number_of_replicas": 0, "number_of_replicas": 0,
"normalizer": {
"lowercase_normalizer": {
"type": "custom",
"char_filter": [],
"filter": ["lowercase"],
}
},
"analysis": { "analysis": {
"filter": { "filter": {
"my_transliterator": { "my_transliterator": {

View File

@ -8,97 +8,30 @@
def search_song(query): def search_song(query):
# Split query into potential track and artist parts
parts = [part.strip() for part in query.split("-")]
track_query = parts[0]
artist_query = parts[1] if len(parts) > 1 else None
search = SongDocument.search() search = SongDocument.search()
# Base queries for track name with high boost # Build a multi_match query that searches in song name, authors' names, and album names
should_queries = [ multi_match_query = ES_Q(
ES_Q("match_phrase", name={"query": track_query, "boost": 10}), "multi_match",
ES_Q("match", name={"query": track_query, "fuzziness": "AUTO", "boost": 8}), query=query,
ES_Q("wildcard", name={"value": f"*{track_query.lower()}*", "boost": 6}), fields=[
ES_Q( "name^5",
"match", "name.raw^10",
name_transliterated={"query": track_query, "fuzziness": "AUTO", "boost": 5}, "name.exact^15",
), "authors.name^4",
] "authors.name.raw^8",
"authors.name.exact^12",
# Add artist-specific queries if artist part exists "album.name^3",
if artist_query: "album.name.raw^6",
should_queries.extend( "album.name.exact^9",
[ ],
ES_Q( fuzziness="AUTO",
"nested", operator="and",
path="authors", type="best_fields",
query=ES_Q(
"match_phrase", name={"query": artist_query, "boost": 4}
),
),
ES_Q(
"nested",
path="authors",
query=ES_Q(
"match",
name={"query": artist_query, "fuzziness": "AUTO", "boost": 3},
),
),
ES_Q(
"nested",
path="authors",
query=ES_Q(
"wildcard",
name={"value": f"*{artist_query.lower()}*", "boost": 2},
),
),
]
)
else:
# If no explicit artist, still search in authors but with lower boost
should_queries.extend(
[
ES_Q(
"nested",
path="authors",
query=ES_Q("match_phrase", name={"query": track_query, "boost": 2}),
),
ES_Q(
"nested",
path="authors",
query=ES_Q(
"match",
name={"query": track_query, "fuzziness": "AUTO", "boost": 1},
),
),
]
)
# Add album queries with lower boost
should_queries.extend(
[
ES_Q(
"nested",
path="album",
query=ES_Q("match_phrase", name={"query": track_query, "boost": 1.5}),
),
ES_Q(
"nested",
path="album",
query=ES_Q(
"match",
name={"query": track_query, "fuzziness": "AUTO", "boost": 1},
),
),
]
) )
# Combine all queries with minimum_should_match=1
search_query = ES_Q("bool", should=should_queries, minimum_should_match=1)
# Execute search with size limit # Execute search with size limit
search = search.query(search_query).extra(size=20) search = search.query(multi_match_query).extra(size=20)
response = search.execute() response = search.execute()
if response.hits: if response.hits: