feat: Add endpoint and service method to retrieve top sounds by play count with filtering options
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user