feat: Add endpoint and service method to retrieve top sounds by play count with filtering options
Some checks failed
Backend CI / lint (push) Failing after 4m54s
Backend CI / test (push) Failing after 4m24s

This commit is contained in:
JSC
2025-08-11 22:04:42 +02:00
parent 53b6c4bca5
commit c69a45c9b4
3 changed files with 151 additions and 2 deletions

View File

@@ -1,12 +1,15 @@
"""Sound repository for database operations."""
from datetime import datetime
from enum import Enum
from sqlalchemy import func
from sqlmodel import col, select
from sqlmodel.ext.asyncio.session import AsyncSession
from app.core.logging import get_logger
from app.models.sound import Sound
from app.models.sound_played import SoundPlayed
from app.repositories.base import BaseRepository
logger = get_logger(__name__)
@@ -224,3 +227,71 @@ class SoundRepository(BaseRepository[Sound]):
except Exception:
logger.exception("Failed to get track statistics")
raise
async def get_top_sounds(
self,
sound_type: str,
date_filter: datetime | None = None,
limit: int = 10,
) -> list[dict]:
"""Get top sounds by play count for a specific type and period using SoundPlayed records."""
try:
# Join SoundPlayed with Sound and count plays within the period
statement = (
select(
Sound.id,
Sound.name,
Sound.type,
Sound.duration,
Sound.created_at,
func.count(SoundPlayed.id).label("play_count")
)
.select_from(SoundPlayed)
.join(Sound, SoundPlayed.sound_id == Sound.id)
)
# Apply sound type filter
if sound_type != "all":
statement = statement.where(Sound.type == sound_type.upper())
# Apply date filter if provided
if date_filter:
statement = statement.where(SoundPlayed.created_at >= date_filter)
# Group by sound and order by play count descending
statement = (
statement
.group_by(
Sound.id,
Sound.name,
Sound.type,
Sound.duration,
Sound.created_at
)
.order_by(func.count(SoundPlayed.id).desc())
.limit(limit)
)
result = await self.session.exec(statement)
rows = result.all()
# Convert to dictionaries with the play count from the period
return [
{
"id": row.id,
"name": row.name,
"type": row.type,
"play_count": row.play_count,
"duration": row.duration,
"created_at": row.created_at,
}
for row in rows
]
except Exception:
logger.exception(
"Failed to get top sounds: type=%s, date_filter=%s, limit=%s",
sound_type,
date_filter,
limit,
)
raise