From 5f50a7ec96c315618e931837876720539717cad6 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sun, 17 May 2026 23:28:52 +0300 Subject: [PATCH] feat(obj-2): mapping backfill via pre-materialized temp tables (117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Continues from migration 116 (trimmed to GIST index only after timeout). Algorithm: 1. Materialize unmapped DOM.РФ ЕКБ objects → _u_domrf (~1056 rows) 2. Materialize unmapped Objective projects → _u_obj (~178 rows) 3. CROSS JOIN LATERAL with top-3 per obj_id, leveraging GIST trgm index from 116 4. Composite score = name_sim*0.6 + dev_match*0.25 + district_match*0.15 5. INSERT auto-accepted (composite >= 0.75) with ON CONFLICT DO NOTHING Why pre-materialize: original CTE recomputed unmapped lists for every row, costing 89M and timing out. Temp tables compute once + GIST index = <30s. Expected: +50-80 mappings, total ~200. Coverage Site Finder competitors улучшится с 15% до ~40-60% (особенно для районов с Объективными devs). --- data/sql/117_obj2_mapping_backfill_fast.sql | 91 +++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 data/sql/117_obj2_mapping_backfill_fast.sql diff --git a/data/sql/117_obj2_mapping_backfill_fast.sql b/data/sql/117_obj2_mapping_backfill_fast.sql new file mode 100644 index 00000000..b6afeea3 --- /dev/null +++ b/data/sql/117_obj2_mapping_backfill_fast.sql @@ -0,0 +1,91 @@ +-- 117_obj2_mapping_backfill_fast.sql +-- Issue #307 OBJ-2 (continued from 116 hotfix). +-- +-- Migration 116 был trimmed до GIST index only из-за heavy CTE timeout. +-- Эта migration делает фактический INSERT через **pre-materialized temp tables** +-- (avoid full CROSS JOIN LATERAL scan). Composite score = name 0.6 + dev 0.25 + district 0.15. +-- Threshold composite >= 0.75. ON CONFLICT DO NOTHING (idempotent). +-- +-- Estimated runtime после оптимизации: <30s (vs old 89M-cost timeout). +-- Coverage цель: +50-80 mappings → объединённый total ~200. + +BEGIN; + +-- Pre-materialize unmapped DOM.РФ ЕКБ objects (~1056 rows) +CREATE TEMP TABLE _u_domrf ON COMMIT DROP AS +SELECT o.obj_id, o.comm_name, o.dev_name, o.district_name, + regexp_replace(lower(coalesce(o.dev_name, '')), '[^а-яa-z0-9]', '', 'g') AS dev_norm + FROM domrf_kn_objects o + WHERE o.is_ekb = true + AND o.comm_name IS NOT NULL + AND NOT EXISTS ( + SELECT 1 FROM objective_complex_mapping m WHERE m.domrf_obj_id = o.obj_id + ); + +-- Pre-materialize distinct unmapped Objective projects (~178 rows) +CREATE TEMP TABLE _u_obj ON COMMIT DROP AS +SELECT DISTINCT + l.project_name, + l.developer, + l.district, + regexp_replace(lower(coalesce(l.developer, '')), '[^а-яa-z0-9]', '', 'g') AS dev_norm + FROM objective_lots l + WHERE l.project_name IS NOT NULL + AND l.project_name NOT IN ( + SELECT objective_complex_name FROM objective_complex_mapping + ); + +-- Top-3 candidates per DOM.РФ obj_id using GIST trgm index (from migration 116) +CREATE TEMP TABLE _pairs ON COMMIT DROP AS +SELECT + d.obj_id, + o.project_name, + o.developer, + o.district, + similarity(d.comm_name, o.project_name) AS name_sim, + (d.dev_norm = o.dev_norm AND d.dev_norm <> '')::int AS dev_match, + ( + coalesce(d.district_name, '') ILIKE '%' || coalesce(o.district, '') || '%' + OR coalesce(o.district, '') ILIKE '%' || coalesce(d.district_name, '') || '%' + )::int AS district_match + FROM _u_domrf d + CROSS JOIN LATERAL ( + SELECT u.project_name, u.developer, u.district, u.dev_norm + FROM _u_obj u + WHERE similarity(d.comm_name, u.project_name) > 0.3 + ORDER BY similarity(d.comm_name, u.project_name) DESC + LIMIT 3 + ) o; + +-- Rank per obj_id by composite score, pick top +WITH ranked AS ( + SELECT + obj_id, project_name, + (name_sim * 0.6 + dev_match * 0.25 + district_match * 0.15) AS composite, + ROW_NUMBER() OVER ( + PARTITION BY obj_id + ORDER BY (name_sim * 0.6 + dev_match * 0.25 + district_match * 0.15) DESC, + name_sim DESC + ) AS rn + FROM _pairs +) +INSERT INTO objective_complex_mapping + (objective_complex_name, domrf_obj_id, objective_group, + match_method, match_score, is_reviewed, note) +SELECT + r.project_name, + r.obj_id, + 'Екатеринбург', + 'multi_feature_v1', + r.composite, + false, + 'OBJ-2 multi-feature 117_fast 2026-05-17 (name 0.6 + dev 0.25 + district 0.15)' + FROM ranked r + WHERE r.rn = 1 + AND r.composite >= 0.75 +ON CONFLICT (objective_complex_name, objective_group) DO NOTHING; + +COMMIT; + +-- REFRESH MV outside tx (CONCURRENTLY requires non-tx) +REFRESH MATERIALIZED VIEW CONCURRENTLY mv_layout_velocity; -- 2.45.3