fix(tradein/dedup): остаток схлопывания домов становится измеряемым числом, а не оценкой (#2690) #2820
Merged
bot-backend
merged 1 commit from 2026-08-10 11:18:20 +00:00
fix/2690-dedup-residual into main
1 commit
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e1586d1307 |
fix(tradein/dedup): остаток схлопывания домов становится измеряемым числом, а не оценкой
All checks were successful
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m58s
#2690 просил ключ, независимый от нормализованного адреса. Проверил на живой таблице все поля houses — независимого наблюдения нет ни одного, и это вывод, а не пауза. cadastral_number 2648 заполнено, ВСЕ 2648 значений различны → схлопывает ноль. Все 2648 несут dadata_enriched_at и house_fias_id, то есть это ответ DaData на нашу же строку адреса. Второй кадастр (KNN-подсказка листингов) отвергнут ещё в #2674: 20.1% значений накрывают >1 здания ГАР. house_fias_id 3678 заполнено, все различны → ФИАС-проход сегодня сливает 0 строк. gar_house_guid перемерено: из 458 пар с общим guid 441 делят канон (guid его повторяет), 17 нет — и 5 из них дальше 250 м, худшая 5064 км. Круговой как был. zhkh_house_guid выглядит внешним реестром и им не является: loader ставит его WHERE gar_house_guid = <guid>, т.е. это И ЕСТЬ ГАР-guid у 4268 из 4663. Из 194 пар с РАЗНЫМ каноном 193 приходят кадастровым фолбэком (та же KNN-подсказка), и 30 из 31 пары дальше 250 м — тоже он. source+ext_house_id / cian_internal_house_id / yandex_jk_id — различны по построению / 39 / 0. координаты настоящее независимое наблюдение, но не идентичность: у соседей общий двор. Уже используются единственным осмысленным способом — как страж. год+этажность ложный свидетель: из 391 пары, которую страж判 не может рассудить, оба поля совпадают у 18 (у 357 есть NULL), зато у 306 пар, отвергнутых стражем дальше 250 м, они совпадают — признак подтвердил бы заведомо неверное. Поэтому ключ не усиливаю. Вместо этого фиксирую остаток числом, которое живёт: перепись после обоих проходов пишет в counters прогона, сколько однокононных строк осталось и ПОЧЕМУ. Разовый замер протухает быстро — «781 лишняя строка» из шапки задачи через четыре дня стала 963, после того как прогон удалил 821. Корзины намеренно НЕ складываются в один «остаток»: «страж молчит» (нет координат у стороны) и «страж отверг» (дальше 250 м) — противоположные факты. Прод 2026-08-10, 963 строки: 568 из них дальше 250 м, медиана 1084 м — это вообще не дубли, канон-ключ о них врёт. Отдельная корзина residual_mergeable — растяжка на сам проход: прошло все стражи и не слилось, ожидание 0. Перепись делит с канон-проходом один и тот же префикс кластеризации (_ranked_cte) — своя копия разъехалась бы с проходом, который описывает, и разъезд был бы невидим. Падение переписи не роняет слияние: слияние — продукт, счётчик — прибор. Прод-сверка ДО мержа: отрендеренный _RESIDUAL_SQL на боевой БД даёт ровно то, что независимо намерено вручную — 963 / 1765 объявлений / 326 молчит / 568 отверг / 8 cross-fias / 61 сольётся. Попутно две правки честности шапки: * снято утверждение «cadastral_number is 100% NULL on prod» — неверно с 2648 строк, и вывод про адресный ключ на нём больше не держится; * записан результат проверки правила выбора победителя (#2690 п.3). Правило было починено в #2674 (listing_cnt DESC NULLS LAST) и проверено задним числом по house_merge_log: из 821 слияния 08.08 ноль выбрали победителя беднее проигравшего. Контрфактика старого правила на тех же кластерах — 6 из 762 забрали бы пустого победителя. Там же предупреждение: мерить победителя до слияния по listings.scraped_at нельзя, #2206 двигает его при ре-подтверждении и порождает 207 несуществующих «худших победителей». Гео-ограждение 250 м не тронуто. Расшивка уже слитого не предлагается. Тесты красные на старом коде: 4 из 4 (KeyError residual_rows / нет _RESIDUAL_SQL). Refs #2690 |