updated song search

This commit is contained in:
Alexander Karpov 2024-12-02 03:16:48 +03:00
parent 1b9b1d2bb5
commit a2607cd0d0
2 changed files with 79 additions and 68 deletions

View File

@ -1,17 +1,20 @@
from functools import wraps
from typing import Any, Dict, Optional
import requests import requests
from typing import Optional, Dict, Any
import structlog import structlog
from django.conf import settings from django.conf import settings
from functools import wraps
logger = structlog.get_logger(__name__) logger = structlog.get_logger(__name__)
class ExternalServiceClient: class ExternalServiceClient:
def __init__(self): def __init__(self):
self.base_url = getattr(settings, 'MUSIC_EXTERNAL_SERVICE_URL', None) self.base_url = getattr(settings, "MUSIC_EXTERNAL_SERVICE_URL", None)
def _make_request(self, endpoint: str, params: Dict = None, **kwargs) -> Optional[Dict]: def _make_request(
self, endpoint: str, params: dict = None, **kwargs
) -> dict | None:
if not self.base_url: if not self.base_url:
return None return None
@ -25,24 +28,19 @@ def _make_request(self, endpoint: str, params: Dict = None, **kwargs) -> Optiona
"External service request failed", "External service request failed",
error=str(e), error=str(e),
endpoint=endpoint, endpoint=endpoint,
params=params params=params,
) )
return None return None
def get_spotify_info(self, track_name: str) -> Optional[Dict[str, Any]]: def get_spotify_info(self, track_name: str) -> dict[str, Any] | None:
return self._make_request( return self._make_request("/spotify/search", params={"query": track_name})
"/spotify/search",
params={"query": track_name}
)
def translate_text(self, text: str, source_lang: str = "auto", target_lang: str = "en") -> Optional[str]: def translate_text(
self, text: str, source_lang: str = "auto", target_lang: str = "en"
) -> str | None:
response = self._make_request( response = self._make_request(
"/translation/translate", "/translation/translate",
json={ json={"text": text, "source_lang": source_lang, "target_lang": target_lang},
"text": text,
"source_lang": source_lang,
"target_lang": target_lang
}
) )
return response.get("translated_text") if response else None return response.get("translated_text") if response else None
@ -52,7 +50,10 @@ def external_service_fallback(fallback_func):
@wraps(fallback_func) @wraps(fallback_func)
def wrapper(*args, **kwargs): def wrapper(*args, **kwargs):
if not hasattr(settings, 'MUSIC_EXTERNAL_SERVICE_URL') or not settings.MUSIC_EXTERNAL_SERVICE_URL: if (
not hasattr(settings, "MUSIC_EXTERNAL_SERVICE_URL")
or not settings.MUSIC_EXTERNAL_SERVICE_URL
):
return fallback_func(*args, **kwargs) return fallback_func(*args, **kwargs)
client = ExternalServiceClient() client = ExternalServiceClient()
@ -68,7 +69,7 @@ def wrapper(*args, **kwargs):
logger.error( logger.error(
"External service failed, falling back to local implementation", "External service failed, falling back to local implementation",
error=str(e), error=str(e),
function=fallback_func.__name__ function=fallback_func.__name__,
) )
return fallback_func(*args, **kwargs) return fallback_func(*args, **kwargs)

View File

@ -8,66 +8,76 @@
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
should_queries = [ should_queries = [
ES_Q("match_phrase", name={"query": query, "boost": 5}), ES_Q("match_phrase", name={"query": track_query, "boost": 10}),
ES_Q( ES_Q("match", name={"query": track_query, "fuzziness": "AUTO", "boost": 8}),
"nested", ES_Q("wildcard", name={"value": f"*{track_query.lower()}*", "boost": 6}),
path="authors",
query=ES_Q("match_phrase", name={"query": query, "boost": 4}),
),
ES_Q(
"nested",
path="album",
query=ES_Q("match_phrase", name={"query": query, "boost": 4}),
),
ES_Q("match", name={"query": query, "fuzziness": "AUTO", "boost": 3}),
ES_Q(
"nested",
path="authors",
query=ES_Q("match", name={"query": query, "fuzziness": "AUTO", "boost": 2}),
),
ES_Q(
"nested",
path="album",
query=ES_Q("match", name={"query": query, "fuzziness": "AUTO", "boost": 2}),
),
ES_Q("wildcard", name={"value": f"*{query.lower()}*", "boost": 1}),
ES_Q(
"nested",
path="authors",
query=ES_Q("wildcard", name={"value": f"*{query.lower()}*", "boost": 0.8}),
),
ES_Q(
"nested",
path="album",
query=ES_Q("wildcard", name={"value": f"*{query.lower()}*", "boost": 0.8}),
),
ES_Q( ES_Q(
"match", "match",
name_transliterated={"query": query, "fuzziness": "AUTO", "boost": 1}, name_transliterated={"query": track_query, "fuzziness": "AUTO", "boost": 5},
),
ES_Q(
"nested",
path="authors",
query=ES_Q(
"match",
name_transliterated={"query": query, "fuzziness": "AUTO", "boost": 0.8},
),
),
ES_Q(
"nested",
path="album",
query=ES_Q(
"match",
name_transliterated={"query": query, "fuzziness": "AUTO", "boost": 0.8},
),
), ),
] ]
# Add artist-specific queries if artist part exists
if artist_query:
should_queries.extend([
ES_Q(
"nested",
path="authors",
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) search_query = ES_Q("bool", should=should_queries, minimum_should_match=1)
# Execute search with size limit
search = search.query(search_query).extra(size=20) search = search.query(search_query).extra(size=20)
response = search.execute() response = search.execute()