feat(backend): Add Heady Jams to leaderboards and optimize queries
Some checks are pending
Deploy Elmeg / deploy (push) Waiting to run
Some checks are pending
Deploy Elmeg / deploy (push) Waiting to run
This commit is contained in:
parent
5c53fbc497
commit
6407c19a29
1 changed files with 63 additions and 20 deletions
|
|
@ -2,7 +2,7 @@ from fastapi import APIRouter, Depends, Query
|
||||||
from sqlmodel import Session, select, func, desc
|
from sqlmodel import Session, select, func, desc
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from database import get_session
|
from database import get_session
|
||||||
from models import Review, Show, Venue, User, Profile
|
from models import Review, Show, Venue, User, Profile, Performance, Song, Rating
|
||||||
|
|
||||||
router = APIRouter(
|
router = APIRouter(
|
||||||
prefix="/leaderboards",
|
prefix="/leaderboards",
|
||||||
|
|
@ -11,25 +11,21 @@ router = APIRouter(
|
||||||
|
|
||||||
@router.get("/shows/top")
|
@router.get("/shows/top")
|
||||||
def get_top_shows(limit: int = 10, session: Session = Depends(get_session)):
|
def get_top_shows(limit: int = 10, session: Session = Depends(get_session)):
|
||||||
"""Get top rated shows based on average review score"""
|
"""Get top rated shows based on average rating"""
|
||||||
# Group by show_id, calc avg score, count reviews
|
# Using Rating table allows for more data points than just text reviews
|
||||||
# Filter for shows with at least 1 review (or maybe 2 to be significant?)
|
|
||||||
|
|
||||||
# SQLModel doesn't support complex group_by/having easily in pure pythonic way sometimes,
|
|
||||||
# but we can use session.exec with a direct select.
|
|
||||||
|
|
||||||
query = (
|
query = (
|
||||||
select(
|
select(
|
||||||
Show,
|
Show,
|
||||||
Venue,
|
Venue,
|
||||||
func.avg(Review.score).label("avg_score"),
|
func.avg(Rating.score).label("avg_score"),
|
||||||
func.count(Review.id).label("review_count")
|
func.count(Rating.id).label("rating_count")
|
||||||
)
|
)
|
||||||
.join(Review, Review.show_id == Show.id)
|
.join(Rating, Rating.show_id == Show.id)
|
||||||
.join(Venue, Show.venue_id == Venue.id)
|
.join(Venue, Show.venue_id == Venue.id)
|
||||||
|
.where(Rating.entity_type == "show")
|
||||||
.group_by(Show.id, Venue.id)
|
.group_by(Show.id, Venue.id)
|
||||||
.having(func.count(Review.id) >= 1)
|
.having(func.count(Rating.id) >= 1)
|
||||||
.order_by(desc("avg_score"), desc("review_count"))
|
.order_by(desc("avg_score"), desc("rating_count"))
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -39,24 +35,32 @@ def get_top_shows(limit: int = 10, session: Session = Depends(get_session)):
|
||||||
{
|
{
|
||||||
"show": show,
|
"show": show,
|
||||||
"venue": venue,
|
"venue": venue,
|
||||||
"avg_score": round(score, 2),
|
"avg_score": round(score, 2) if score else 0,
|
||||||
"review_count": count
|
"review_count": count
|
||||||
}
|
}
|
||||||
for show, venue, score, count in results
|
for show, venue, score, count in results
|
||||||
]
|
]
|
||||||
|
|
||||||
@router.get("/venues/top")
|
@router.get("/performances/top")
|
||||||
def get_top_venues(limit: int = 10, session: Session = Depends(get_session)):
|
def get_top_performances(limit: int = 20, session: Session = Depends(get_session)):
|
||||||
"""Get top rated venues"""
|
"""Get top rated performances (Heady Jams)"""
|
||||||
query = (
|
query = (
|
||||||
select(
|
select(
|
||||||
|
Performance,
|
||||||
|
Song,
|
||||||
|
Show,
|
||||||
Venue,
|
Venue,
|
||||||
func.avg(Review.score).label("avg_score"),
|
func.avg(Rating.score).label("avg_score"),
|
||||||
func.count(Review.id).label("review_count")
|
func.count(Rating.id).label("rating_count")
|
||||||
)
|
)
|
||||||
.join(Review, Review.venue_id == Venue.id)
|
.join(Rating, Rating.performance_id == Performance.id)
|
||||||
.group_by(Venue.id)
|
.join(Song, Performance.song_id == Song.id)
|
||||||
.order_by(desc("avg_score"))
|
.join(Show, Performance.show_id == Show.id)
|
||||||
|
.join(Venue, Show.venue_id == Venue.id)
|
||||||
|
.where(Rating.entity_type == "performance")
|
||||||
|
.group_by(Performance.id, Song.id, Show.id, Venue.id)
|
||||||
|
.having(func.count(Rating.id) >= 1)
|
||||||
|
.order_by(desc("avg_score"), desc("rating_count"))
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -64,8 +68,46 @@ def get_top_venues(limit: int = 10, session: Session = Depends(get_session)):
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
"performance": performance,
|
||||||
|
"song": song,
|
||||||
|
"show": show,
|
||||||
"venue": venue,
|
"venue": venue,
|
||||||
"avg_score": round(score, 2),
|
"avg_score": round(score, 2) if score else 0,
|
||||||
|
"rating_count": count
|
||||||
|
}
|
||||||
|
for performance, song, show, venue, score, count in results
|
||||||
|
]
|
||||||
|
|
||||||
|
@router.get("/venues/top")
|
||||||
|
def get_top_venues(limit: int = 10, session: Session = Depends(get_session)):
|
||||||
|
"""Get top rated venues based on show ratings there?"""
|
||||||
|
# A venue's rating is often derivative of the shows there, or specific venue ratings.
|
||||||
|
# Let's assume venue rating directly for now if entity_type='venue' exists,
|
||||||
|
# otherwise we might avg show ratings. Let's start with direct venue ratings.
|
||||||
|
|
||||||
|
query = (
|
||||||
|
select(
|
||||||
|
Venue,
|
||||||
|
func.avg(Rating.score).label("avg_score"),
|
||||||
|
func.count(Rating.id).label("rating_count")
|
||||||
|
)
|
||||||
|
.join(Rating, Rating.venue_id == Venue.id)
|
||||||
|
.where(Rating.entity_type == "venue")
|
||||||
|
.group_by(Venue.id)
|
||||||
|
.having(func.count(Rating.id) >= 1)
|
||||||
|
.order_by(desc("avg_score"))
|
||||||
|
.limit(limit)
|
||||||
|
)
|
||||||
|
|
||||||
|
results = session.exec(query).all()
|
||||||
|
|
||||||
|
# Fallback: if no direct venue ratings, maybe average the shows played there?
|
||||||
|
# Keeping it simple for now.
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"venue": venue,
|
||||||
|
"avg_score": round(score, 2) if score else 0,
|
||||||
"review_count": count
|
"review_count": count
|
||||||
}
|
}
|
||||||
for venue, score, count in results
|
for venue, score, count in results
|
||||||
|
|
@ -73,7 +115,8 @@ def get_top_venues(limit: int = 10, session: Session = Depends(get_session)):
|
||||||
|
|
||||||
@router.get("/users/active")
|
@router.get("/users/active")
|
||||||
def get_active_users(limit: int = 10, session: Session = Depends(get_session)):
|
def get_active_users(limit: int = 10, session: Session = Depends(get_session)):
|
||||||
"""Get users with most reviews"""
|
"""Get users with most reviews/ratings"""
|
||||||
|
# Combining reviews count
|
||||||
query = (
|
query = (
|
||||||
select(
|
select(
|
||||||
Profile,
|
Profile,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue