elmeg-demo/backend/routers/search.py
fullsizemalt 8990063837 fix: search endpoint crashing on User.username reference
User.username doesn't exist - usernames are in Profile model.
Now properly searches Profile.username and joins results.
2025-12-24 21:49:10 -08:00

117 lines
3.2 KiB
Python

from typing import List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlmodel import Session, select, col
from sqlalchemy.orm import selectinload
from database import get_session
from models import Show, Song, Venue, Tour, User, Group, Performance, PerformanceNickname, Comment, Review
from schemas import ShowRead, SongRead, VenueRead, TourRead, UserRead, GroupRead
router = APIRouter(prefix="/search", tags=["search"])
@router.get("/")
def global_search(
q: str,
session: Session = Depends(get_session),
limit: int = 5
):
if len(q) < 2:
return {}
q_str = f"%{q}%"
# Search Songs
songs = session.exec(
select(Song)
.where(col(Song.title).ilike(q_str))
.limit(limit)
).all()
# Search Venues
venues = session.exec(
select(Venue)
.where(col(Venue.name).ilike(q_str))
.limit(limit)
).all()
# Search Tours
tours = session.exec(
select(Tour)
.where(col(Tour.name).ilike(q_str))
.limit(limit)
).all()
# Search Groups
groups = session.exec(
select(Group)
.where(col(Group.name).ilike(q_str))
.limit(limit)
).all()
# Search Users (by email or profile username)
users = session.exec(
select(User)
.where(col(User.email).ilike(q_str))
.limit(limit)
).all()
# Also search Profiles for username matches
from models import Profile
profile_matches = session.exec(
select(Profile)
.where(col(Profile.username).ilike(q_str))
.limit(limit)
).all()
# Add unique users from profile matches
existing_user_ids = {u.id for u in users}
for p in profile_matches:
if p.user_id not in existing_user_ids:
user = session.get(User, p.user_id)
if user:
users.append(user)
existing_user_ids.add(user.id)
# Search Nicknames
nicknames = session.exec(
select(PerformanceNickname)
.options(selectinload(PerformanceNickname.performance).selectinload(Performance.song))
.where(col(PerformanceNickname.nickname).ilike(q_str))
.where(PerformanceNickname.status == "approved")
.limit(limit)
).all()
# Search Performances
performances = session.exec(
select(Performance)
.options(selectinload(Performance.song), selectinload(Performance.show))
.where(col(Performance.notes).ilike(q_str))
.limit(limit)
).all()
# Search Reviews
reviews = session.exec(
select(Review)
.where(
(col(Review.blurb).ilike(q_str)) |
(col(Review.content).ilike(q_str))
)
.limit(limit)
).all()
# Search Comments
comments = session.exec(
select(Comment)
.where(col(Comment.content).ilike(q_str))
.limit(limit)
).all()
return {
"songs": songs,
"venues": venues,
"tours": tours,
"groups": groups,
"users": users,
"nicknames": nicknames,
"performances": performances,
"reviews": reviews,
"comments": comments
}