2025-06-05 06:00:02 +00:00

103 lines
3.0 KiB
Python

from typing import List
from sqlalchemy.orm import Session
from sqlalchemy import func, desc
from app.models.song import Song, song_playlist
from app.models.playlist import Playlist
from app.models.artist import Artist
def get_similar_songs(db: Session, song_id: int, limit: int = 10) -> List[Song]:
"""
Get similar songs based on the same artist and album.
"""
# Get the current song
current_song = db.query(Song).filter(Song.id == song_id).first()
if not current_song:
return []
# Find songs from the same artist and album (if applicable)
query = db.query(Song).filter(Song.id != song_id)
if current_song.album_id:
# Prioritize songs from same album
query = query.filter(Song.album_id == current_song.album_id)
else:
# Otherwise, find songs from the same artist
query = query.filter(Song.artist_id == current_song.artist_id)
return query.limit(limit).all()
def get_recommended_songs_for_user(db: Session, user_id: int, limit: int = 10) -> List[Song]:
"""
Get song recommendations for a user based on their playlists.
"""
# First get all songs in user's playlists
user_playlist_songs = (
db.query(Song.id)
.join(song_playlist)
.join(Playlist)
.filter(Playlist.user_id == user_id)
.subquery()
)
# Get artists that the user listens to
user_artists = (
db.query(Artist.id)
.join(Song, Song.artist_id == Artist.id)
.join(user_playlist_songs, user_playlist_songs.c.id == Song.id)
.distinct()
.subquery()
)
# Recommend songs from the same artists that aren't in the user's playlists
recommended = (
db.query(Song)
.join(Artist, Song.artist_id == Artist.id)
.filter(
Song.id.notin_(user_playlist_songs),
Artist.id.in_(user_artists)
)
.order_by(func.random())
.limit(limit)
.all()
)
return recommended
def get_popular_songs(db: Session, limit: int = 10) -> List[Song]:
"""
Get popular songs based on how many playlists they appear in.
"""
# Count the number of playlists each song is in
song_counts = (
db.query(
Song,
func.count(song_playlist.c.playlist_id).label("playlist_count")
)
.join(song_playlist)
.group_by(Song.id)
.order_by(desc("playlist_count"))
.limit(limit)
.all()
)
# Extract just the songs
return [song for song, _ in song_counts]
def get_artist_recommendations(db: Session, artist_id: int, limit: int = 5) -> List[Artist]:
"""
Get similar artists based on the given artist.
"""
# This is a very simple implementation that just returns random artists
# In a real system, this would use more sophisticated algorithms
return (
db.query(Artist)
.filter(Artist.id != artist_id)
.order_by(func.random())
.limit(limit)
.all()
)