From b613ac6827fc2f369b1f0b146b4d138fcd353521 Mon Sep 17 00:00:00 2001 From: goon-foss Date: Fri, 16 Oct 2026 11:32:37 +0200 Subject: [PATCH] fix(scenes): sceny o identycznym tytule zawsze w puli kandydatow find_blocking_candidates OR-owal dokladny tytul z blokiem studio/data pod jednym LIMIT 50 bez kolejnosci. Samo okno dat to ok. 45 tys. scen, wiec scena o identycznym tytule trafiala do puli w 17% przypadkow (probka 120). Teraz tytul idzie osobnym zapytaniem po indeksie, a blok studio+data od najblizszej daty. Sredni czas spadl z 12 do 4 ms. Co-Authored-By: Claude Opus 5.5 --- app/resolve/scene_match.py | 39 +++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/app/resolve/scene_match.py b/app/resolve/scene_match.py index ff338c6..438f9f3 100644 --- a/app/resolve/scene_match.py +++ b/app/resolve/scene_match.py @@ -4,7 +4,7 @@ from __future__ import annotations import uuid from datetime import date, timedelta -from sqlalchemy import and_, or_, select, text +from sqlalchemy import and_, func, select, text from sqlalchemy.orm import Session from app.config import get_settings @@ -165,12 +165,29 @@ def find_blocking_candidates( - jeśli mamy studio + date → studio_id == X AND date BETWEEN ±window_days - jeśli mamy tylko date → date BETWEEN ±window_days - jeśli mamy tylko studio → studio_id == X - - dodatkowo, jeśli `title_normalized` podany, OR-uj exact title match - (przydaje się gdy date/studio brakuje) + - dodatkowo, jeśli `title_normalized` podany, sceny o identycznym tytule + + Sceny o identycznym tytule ida osobnym zapytaniem i zawsze trafiaja do puli. Do + 2026-10-16 byly OR-owane z blokiem pod jednym LIMIT bez kolejnosci, a samo okno dat + to ok. 45 tys. scen, wiec dokladny duplikat potrafil wypasc (ten sam blad co przy + filmach, find_movie_candidates). Blok studio+data idzie od najblizszej daty (12 ms + dla najwiekszego studia); kolejnosc po podobienstwie tytulu kosztowala 0,4-3 s na + scene, za drogo na ingest. """ if window_days is None: window_days = get_settings().date_window_days + out: list[Scene] = [] + if title_normalized: + out = list( + session.execute( + select(Scene) + .where(Scene.title_normalized == title_normalized) + .order_by(Scene.created_at.desc()) + .limit(limit) + ).scalars().all() + ) + conds = [] if studio_id is not None and release_date is not None: conds.append( @@ -191,11 +208,15 @@ def find_blocking_candidates( elif studio_id is not None: conds.append(Scene.studio_id == studio_id) - if title_normalized: - conds.append(Scene.title_normalized == title_normalized) - if not conds: - return [] + return out - stmt = select(Scene).where(or_(*conds)).limit(limit) - return list(session.execute(stmt).scalars().all()) + stmt = select(Scene).where(*conds) + if studio_id is not None and release_date is not None: + stmt = stmt.order_by(func.abs(Scene.release_date - release_date)) + seen = {s.id for s in out} + for s in session.execute(stmt.limit(limit)).scalars().all(): + if s.id not in seen: + seen.add(s.id) + out.append(s) + return out