goon/app/models/__init__.py
goon-foss 3de8489ffa fix(dedup): blacklista zdegenerowanych phashy + scalenie 4647 duplikatow
Audyt duplikatow po phashu miniatur wykazal dwa rozne zjawiska, ktore wygladaly
jak jedno.

1. Zdegenerowane phashe. 73 wartosci wystepowaly przy >=10 scenach kazda, lacznie
przy 4375 scenach; rekordzistka byla dzielona przez 892 sceny o 892 roznych
tytulach i 1886 roznych performerach. To zaslepki i czarne klatki, nie odciski
scen. find_by_phash_within bierze najblizsza wartosc z calej tabeli, wiec taka
zaslepka zawsze wygrywala z prawdziwym duplikatem (dist 0). Do tej pory bronila
nas bramka dur_prox i nic sie nie skleilo, ale to zabezpieczenie drugiej linii.

Blacklista jest tabela, nie jednorazowym DELETE, bo sam DELETE nic nie daje:
zaslepka wraca przy kolejnym ingescie. Trzeba pamietac, ze wartosc jest
bezuzyteczna. Job co 24h dopisuje nowe i czysci odciski. Po czyszczeniu zero
grup >=10, najwieksza pozostala ma 9.

2. Realne duplikaty. 4647 scalonych. Przyczyna byla jedna: 97 procent par ma
perverzije po dokladnie jednej stronie, bo pisze tytuly z prefiksem studia i
performera, a reszta tubow daje goly tytul. Wbrew mojej pierwszej diagnozie NIE
trzeba tu ruszac scoringu tytulu (token_set_ratio i tak radzi sobie z prefiksem,
a sciezka phash idzie przed composite): 80 procent par to dlug sprzed 60+ dni, a
biezacy wyciek to okolo 1 dziennie. Nadmiarowe wiersze: 18452 na 9449.

merge_phash_exact_dupes.py dostal wykluczenie blacklisty. Bez tego byl grozny:
sam klaster 892 scen dawal ~397 tys. par do rozwazenia.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 12:47:20 +02:00

74 lines
2.1 KiB
Python

from app.models.base import Base
from app.models.blacklist import BlacklistedPerformer, BlacklistedStudio, BlacklistedTag
from app.models.bug_report import BugReport
from app.models.external_record import ExternalRecord
from app.models.favorite_movie import FavoriteMovie
from app.models.favorite_performer import FavoritePerformer
from app.models.favorite_scene import FavoriteScene
from app.models.favorite_studio import FavoriteStudio
from app.models.ingest_run import IngestRun
from app.models.merge_candidate import MergeCandidate
from app.models.movie import (
Movie,
MovieChapter,
MovieExternalRef,
MoviePerformer,
MovieTag,
)
from app.models.movie_playback_source import MoviePlaybackSource
from app.models.performer import Performer, PerformerAlias, PerformerExternalRef
from app.models.play_progress import MoviePlayProgress, ScenePlayProgress
from app.models.playback_event import PlaybackEvent
from app.models.playback_source import PlaybackSource
from app.models.phash_blacklist import PhashBlacklist
from app.models.saved_search import SavedSearch
from app.models.source_stats import SourceStats
from app.models.scene import (
Scene,
SceneExternalRef,
SceneFingerprint,
ScenePerformer,
SceneTag,
)
from app.models.source import Source
from app.models.studio import Studio, StudioAlias, StudioExternalRef
from app.models.tag import Tag
__all__ = [
"Base",
"BlacklistedPerformer",
"BlacklistedStudio",
"BlacklistedTag",
"BugReport",
"ExternalRecord",
"FavoriteMovie",
"FavoritePerformer",
"FavoriteScene",
"FavoriteStudio",
"IngestRun",
"MergeCandidate",
"Movie",
"MovieChapter",
"MovieExternalRef",
"MoviePerformer",
"MoviePlaybackSource",
"MovieTag",
"Performer",
"PerformerAlias",
"PerformerExternalRef",
"MoviePlayProgress",
"ScenePlayProgress",
"PlaybackSource",
"PhashBlacklist",
"SavedSearch",
"Scene",
"SceneExternalRef",
"SceneFingerprint",
"ScenePerformer",
"SceneTag",
"Source",
"Studio",
"StudioAlias",
"StudioExternalRef",
"Tag",
]