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:
parent
ce174b671e
commit
cd34b296e2
1 changed files with 41 additions and 8 deletions
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue