fix(tradein): вернуть фотографии подсказок Avito IMV задним числом (#2674)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
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 3m1s

Класс «площадка прислала, парсер разобрал, до базы не доехало». Правка #2682
починила ПУТЬ (парсер отдаёт imageLink, INSERT его перечисляет), но только для
будущих строк — исторические так и остались с NULL.

Прод 2026-08-06, точные count(*):
  house_suggestions            25 055 строк, image_link заполнен у 0
  house_imv_evaluations         2 685 строк, raw_response есть у 2 685,
                                suggestions.items[0].imageLink есть у 2 685

Сырьё сохранено целиком, поэтому исторические ВОССТАНОВИМЫ: ключ подсказки
(house_id, ext_item_id) однозначно ложится на (e.house_id, item->>'id').
SELECT-прогон того же JOIN на проде: 21 480 из 25 055 (85.7%) восстановимо.

Остальные 3 575 невосстановимы в принципе, и это не недоделанный бэкфилл:
house_imv_evaluations имеет UNIQUE(house_id) и ON CONFLICT DO UPDATE, поэтому
повторная оценка дома перетирает raw_response — старый набор подсказок остаётся
без своего сырья. Пишу это в комментарий к колонке, чтобы следующий читатель
не искал баг в разнице 25 055 vs 21 480.

Идемпотентно: WHERE image_link IS NULL — повтор не трогает заполненное и не
перетирает то, что напишет живой скрейпер.
This commit is contained in:
bot-backend 2026-08-06 05:57:00 +05:00
parent fb5ec56a54
commit 521d35fe49

View file

@ -0,0 +1,44 @@
-- 221_backfill_house_suggestions_image_link.sql
-- Purpose (#2674, класс «площадка прислала, парсер разобрал, до базы не доехало»):
-- вернуть фотографии подсказок Avito IMV задним числом.
--
-- Контекст. Колонка house_suggestions.image_link существует с миграции 064; до
-- PR #2682 (2026-08-06) парсер выбрасывал suggestions.items[].imageLink, а INSERT
-- её не перечислял. Правка #2682 чинит только БУДУЩИЕ строки. На проде на момент
-- этой миграции: 25 055 строк house_suggestions, image_link заполнен у 0 (count
-- точный, не reltuples).
--
-- Почему исторические ВОССТАНОВИМЫ. Полный ответ /web/1/realty-imv/get-data
-- сохраняется целиком в house_imv_evaluations.raw_response (jsonb) — 2 685 строк,
-- у ВСЕХ 2 685 присутствует suggestions.items[0].imageLink. Ключ подсказки
-- (house_id, ext_item_id) однозначно соответствует (e.house_id, item->>'id').
--
-- Прод-замер ДО (SELECT-прогон этого же JOIN, 2026-08-06):
-- всего 25 055 · восстановимо 21 480 (85.7%) · не восстановимо 3 575 (14.3%).
-- 3 575 — это подсказки, чей house_id переоценивался позже: house_imv_evaluations
-- имеет UNIQUE(house_id) и ON CONFLICT DO UPDATE перетирает raw_response свежим
-- ответом, поэтому старый набор подсказок остаётся без своего сырья. Эти строки
-- невосстановимы в принципе — не «недоделанный бэкфилл», а утраченный источник.
--
-- Идемпотентно: WHERE hs.image_link IS NULL — повторный прогон не трогает уже
-- заполненные строки и не перетирает то, что напишет живой скрейпер.
--
-- Apply after: 216_dead_code_sweep.sql
BEGIN;
UPDATE house_suggestions hs
SET image_link = j.item ->> 'imageLink'
FROM house_imv_evaluations e
CROSS JOIN LATERAL jsonb_array_elements(e.raw_response -> 'suggestions' -> 'items') AS j(item)
WHERE e.house_id = hs.house_id
AND j.item ->> 'id' = hs.ext_item_id
AND hs.image_link IS NULL
AND nullif(j.item ->> 'imageLink', '') IS NOT NULL;
COMMENT ON COLUMN house_suggestions.image_link IS
'Ссылка на фото лота (suggestions.items[].imageLink). Пишется скрейпером с #2682; '
'исторические строки восстановлены из house_imv_evaluations.raw_response миграцией 221 '
'(21 480 из 25 055; остальные потеряли сырьё при перезаписи оценки дома).';
COMMIT;