fix(performers): szukanie po aliasach i w odwrotnej kolejnosci slow

Zgloszenie 436121fb: "Takase Rina" (japonska kolejnosc) nie znajdowalo
"Rina Takase" (15 scen) i wygladalo, jakby jej nie bylo. Wyszukiwanie
patrzy teraz na podciag nazwy albo aliasu, dla dwoch slow tez w odwrotnej
kolejnosci; trafienia w nazwie ida przed trafieniami tylko w aliasie.
Obie kolumny maja indeksy trigramowe, 0,2 do 1,1 s w sandboksie.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
goon-foss 2026-10-12 09:56:59 +02:00
parent ce174b671e
commit cd34b296e2

View file

@ -15,14 +15,14 @@ from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, ConfigDict
from sqlalchemy import and_, exists, func, select
from sqlalchemy import and_, case, exists, func, or_, select
from sqlalchemy.orm import Session
from app.auth import require_api_key
from app.db import get_session
from app.models.movie import Movie, MovieTag
from app.models.movie_playback_source import MoviePlaybackSource
from app.models.performer import Performer
from app.models.performer import Performer, PerformerAlias
from app.models.playback_source import PlaybackSource
from app.models.scene import ScenePerformer, SceneTag
from app.models.studio import Studio
@ -30,6 +30,37 @@ from app.models.tag import Tag
from app.models.tag_vertical_count import TagVerticalCount
from app.verticals import VERTICALS
def _performer_name_patterns(q: str) -> list[str]:
qn = " ".join(q.lower().split())
pats = [f"%{qn}%"]
words = qn.split(" ")
if len(words) == 2:
pats.append(f"%{words[1]} {words[0]}%")
return pats
def _performer_name_rank(q: str):
"""0 = trafienie w nazwie, 1 = tylko w aliasie; sortujemy po tym przed liczba scen,
inaczej "anna" dawalo na gorze duze nazwiska z aliasem "Adrianna"."""
return case((or_(*[Performer.name_normalized.ilike(p) for p in _performer_name_patterns(q)]), 0), else_=1)
def _performer_name_clause(q: str):
"""Szukanie wykonawcy: podciag nazwy ALBO aliasu, a dla dwoch slow tez w odwrotnej
kolejnosci. Zgloszenie 436121fb: "Takase Rina" (japonska kolejnosc) nie znajdowalo
"Rina Takase" i wygladalo, jakby jej nie bylo. Obie kolumny maja indeksy trigramowe."""
pats = _performer_name_patterns(q)
return or_(
*[Performer.name_normalized.ilike(p) for p in pats],
exists(
select(1).where(
PerformerAlias.performer_id == Performer.id,
or_(*[PerformerAlias.alias_normalized.ilike(p) for p in pats]),
)
),
)
log = logging.getLogger(__name__)
router = APIRouter(tags=["taxonomies"], dependencies=[Depends(require_api_key)])
@ -294,14 +325,15 @@ def list_performers(
.join(v_count, v_count.c.performer_id == Performer.id)
)
if q:
base = base.where(Performer.name_normalized.ilike(f"%{q.lower()}%"))
base = base.where(_performer_name_clause(q))
total = session.execute(
select(func.count()).select_from(base.subquery())
).scalar_one()
rank = [_performer_name_rank(q)] if q else []
if order in ("scene_count", "popular"):
ordered = base.order_by(v_count.c.c.desc(), Performer.canonical_name.asc())
ordered = base.order_by(*rank, v_count.c.c.desc(), Performer.canonical_name.asc())
else:
ordered = base.order_by(Performer.canonical_name.asc())
ordered = base.order_by(*rank, Performer.canonical_name.asc())
rows = session.execute(
ordered.offset((page - 1) * per_page).limit(per_page)
).all()
@ -323,18 +355,19 @@ def list_performers(
# 3M scene_performers + EXISTS playback per-request. Patrz migracja 0019.
base = select(Performer)
if q:
base = base.where(Performer.name_normalized.ilike(f"%{q.lower()}%"))
base = base.where(_performer_name_clause(q))
total = session.execute(
select(func.count()).select_from(base.subquery())
).scalar_one()
rank = [_performer_name_rank(q)] if q else []
if order in ("scene_count", "popular"):
ordered = base.order_by(
Performer.scene_count.desc(), Performer.canonical_name.asc()
*rank, Performer.scene_count.desc(), Performer.canonical_name.asc()
)
else:
ordered = base.order_by(Performer.canonical_name.asc())
ordered = base.order_by(*rank, Performer.canonical_name.asc())
perfs_page = session.execute(
ordered.offset((page - 1) * per_page).limit(per_page)