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 fastapi import APIRouter, Depends, HTTPException, Query
|
||||||
from pydantic import BaseModel, ConfigDict
|
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 sqlalchemy.orm import Session
|
||||||
|
|
||||||
from app.auth import require_api_key
|
from app.auth import require_api_key
|
||||||
from app.db import get_session
|
from app.db import get_session
|
||||||
from app.models.movie import Movie, MovieTag
|
from app.models.movie import Movie, MovieTag
|
||||||
from app.models.movie_playback_source import MoviePlaybackSource
|
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.playback_source import PlaybackSource
|
||||||
from app.models.scene import ScenePerformer, SceneTag
|
from app.models.scene import ScenePerformer, SceneTag
|
||||||
from app.models.studio import Studio
|
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.models.tag_vertical_count import TagVerticalCount
|
||||||
from app.verticals import VERTICALS
|
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__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
router = APIRouter(tags=["taxonomies"], dependencies=[Depends(require_api_key)])
|
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)
|
.join(v_count, v_count.c.performer_id == Performer.id)
|
||||||
)
|
)
|
||||||
if q:
|
if q:
|
||||||
base = base.where(Performer.name_normalized.ilike(f"%{q.lower()}%"))
|
base = base.where(_performer_name_clause(q))
|
||||||
total = session.execute(
|
total = session.execute(
|
||||||
select(func.count()).select_from(base.subquery())
|
select(func.count()).select_from(base.subquery())
|
||||||
).scalar_one()
|
).scalar_one()
|
||||||
|
rank = [_performer_name_rank(q)] if q else []
|
||||||
if order in ("scene_count", "popular"):
|
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:
|
else:
|
||||||
ordered = base.order_by(Performer.canonical_name.asc())
|
ordered = base.order_by(*rank, Performer.canonical_name.asc())
|
||||||
rows = session.execute(
|
rows = session.execute(
|
||||||
ordered.offset((page - 1) * per_page).limit(per_page)
|
ordered.offset((page - 1) * per_page).limit(per_page)
|
||||||
).all()
|
).all()
|
||||||
|
|
@ -323,18 +355,19 @@ def list_performers(
|
||||||
# 3M scene_performers + EXISTS playback per-request. Patrz migracja 0019.
|
# 3M scene_performers + EXISTS playback per-request. Patrz migracja 0019.
|
||||||
base = select(Performer)
|
base = select(Performer)
|
||||||
if q:
|
if q:
|
||||||
base = base.where(Performer.name_normalized.ilike(f"%{q.lower()}%"))
|
base = base.where(_performer_name_clause(q))
|
||||||
|
|
||||||
total = session.execute(
|
total = session.execute(
|
||||||
select(func.count()).select_from(base.subquery())
|
select(func.count()).select_from(base.subquery())
|
||||||
).scalar_one()
|
).scalar_one()
|
||||||
|
|
||||||
|
rank = [_performer_name_rank(q)] if q else []
|
||||||
if order in ("scene_count", "popular"):
|
if order in ("scene_count", "popular"):
|
||||||
ordered = base.order_by(
|
ordered = base.order_by(
|
||||||
Performer.scene_count.desc(), Performer.canonical_name.asc()
|
*rank, Performer.scene_count.desc(), Performer.canonical_name.asc()
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
ordered = base.order_by(Performer.canonical_name.asc())
|
ordered = base.order_by(*rank, Performer.canonical_name.asc())
|
||||||
|
|
||||||
perfs_page = session.execute(
|
perfs_page = session.execute(
|
||||||
ordered.offset((page - 1) * per_page).limit(per_page)
|
ordered.offset((page - 1) * per_page).limit(per_page)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue