-- 169_obj_class_fallback.sql -- -- Контекст (issue #38 — Demand D6): kn-API не отдаёт obj_class для ~3032 ЖК -- Свердл (Bug_Kn_API_Obj_Class_Always_Null). Это ломает per-class velocity (D2), -- per-class absorption (D3) и per-class weight profile (I2). -- -- Workaround: fuzzy name-match domrf_kn_objects.comm_name ↔ yandex_realty_zk.name -- через pg_trgm similarity(); опционально — price-inference по -- yandex_realty_class_prices. Результат пишется в obj_class_fallback с пометкой -- источника obj_class_source ('domrf' | 'yandex_match' | 'price_inference'). -- Backfill выполняет ETL-модуль app.services.etl.obj_class_backfill. -- -- Порядок применения: схема первой (этот файл), затем backend-код, -- читающий COALESCE(obj_class, obj_class_fallback). -- -- Idempotent: ADD COLUMN IF NOT EXISTS + CREATE INDEX IF NOT EXISTS + CREATE -- EXTENSION IF NOT EXISTS. Безопасно ре-применять. BEGIN; -- ── Колонки fallback ──────────────────────────────────────────────────────── -- obj_class_fallback — производный класс (когда реальный obj_class = NULL). -- obj_class_source — провенанс класса: -- 'domrf' — реальный obj_class из kn-API/AI-описания (этим файлом -- не проставляется; для аудита, проставляет backfill). -- 'yandex_match' — trigram-match comm_name ↔ yandex_realty_zk.name. -- 'price_inference' — выведен по price_per_m2 vs yandex_realty_class_prices. ALTER TABLE domrf_kn_objects ADD COLUMN IF NOT EXISTS obj_class_fallback TEXT, ADD COLUMN IF NOT EXISTS obj_class_source TEXT; -- ── pg_trgm + GIN trgm индексы для similarity() perf ───────────────────────── -- similarity(LOWER(a), LOWER(b)) без GIN trgm деградирует в seq-scan на каждой -- паре (CROSS JOIN LATERAL). Индексы по выражению LOWER(...) ускоряют % / <-> . CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE INDEX IF NOT EXISTS idx_domrf_kn_objects_comm_name_trgm ON domrf_kn_objects USING gin (LOWER(comm_name) gin_trgm_ops); CREATE INDEX IF NOT EXISTS idx_yandex_realty_zk_name_trgm ON yandex_realty_zk USING gin (LOWER(name) gin_trgm_ops); -- ── Документация ──────────────────────────────────────────────────────────── COMMENT ON COLUMN domrf_kn_objects.obj_class_fallback IS 'Производный класс жилья, когда реальный obj_class = NULL (issue #38). ' 'Источник в obj_class_source. Backfill: app.services.etl.obj_class_backfill.'; COMMENT ON COLUMN domrf_kn_objects.obj_class_source IS 'Провенанс класса: domrf | yandex_match | price_inference (issue #38).'; COMMIT;