ГАР БД ФИАС или очень полная БД ФИАС

01.06.2020 ИФНС опубликовала новый формат выгрузки данных
17.12.2020 Мягко намекнула, что в 2021 будет использоваться только он
01.09.2021 Это свершилось: теперь просто «полная БД ФИАС» перестала обновляться и требуется использовать ГАР БД ФИАС

Частично импортируем ГАР БД ФИАС в MySQL на PHP.

Новость, мягко говоря, не очень, для тех кому нужно получить иерархию улиц и список домов с почтовыми индексами, особенно учитывая, что КЛАДР до сих жив. А не очень из-за того, что файлик данных с 12Гб резко пополнел до 28Гб. Конечно, можно возразить, что скачал один раз и по чуть-чуть обновляйся. Да, можно, если хранить нужные файлы данных целиком и постоянно накатывать на них обновления, но… наличие багов (даже в полной версии) добавит радости.

Небольшой офф

Возможно имеет смысл написать небольшую библиотеку, функционал которой — скачивать только необходимую часть zip архива для распаковки конкретного файла с web сервера, поддерживающего докачку. Весьма актуально, т.к. из этих 28Гб требуется значительно меньшая часть. Если вы знаете, что это уже есть где-то «из коробки» или реализовано отдельной библиотекой — пожалуйста, напишите.

Теперь новая БД содержит иерархическую информацию об адресных объектах в двух вариантах:
— по административно-территориальному устройству (для упорядоченного осуществления функций государственного управления) — на основе этого код ОКАТО
— по муниципальному устройству (для организации местного самоуправления) — соответственно, ОКТМО
Не каждый объект «доступен» в обоих иерархиях. Например, если мы возьмём г. Карабулак, то по административно-территориальному устройству он находится в республике Ингушетия, а по муниципальному устройству расположен городском округе города Карабулак, который в свою очередь в республике Ингушетия и «не участвует» в административно-территориальном устройстве.

Моей целью является получение двух таблиц только с актуальной на момент импорта информацией об иерархической структуре адресов (от региона до, обычно, улицы) и списка жилых домов (не интересуют гаражи, шахты, подвалы…) с почтовыми индексами. NB! При выборе адреса в реальных проектах рекомендую сохранять полный иерархический путь, а не только идентификатор — впоследствии адрес может стать неактуальным (выбрать его нельзя — дома реально нет, а сохранить информацию корректно необходимо).

Таблица gar_addr, ключевое поле id. Иерархию определяют указывающие на него owner_adm и owner_mun. Субъекты РФ (и Байконур) имеют level=1, owner_adm=owner_mun=0. Содержит информацию о названиях адресных объектов (NAME, TYPENAME) и говорящие за себя OKATO, OKTMO, KLADR. OBJECTGUID, ранее в ФИАС именовался AOGUID, является идентификатором адресного объекта (уникальный для актуальных записей; не уникальный, если используются исторические устаревшие записи). OBJECTID аналогичен по значению OBJECTGUID, но уже целочисленный.

image-loader.svg

Таблица gar_house — список домов. owner_* указывает на gar_addr.id.
Содержит номер дома в 3 полях: основной и 2 дополнительных (и это не я придумал, ADDNUM2 в актуальных данных отсутствует, хотя ранее использовался) и, соответственно, их типы (например: дом, литера, корпус). Описание этих значений в AS_HOUSE_TYPES…XML. ОКАТО и ОКТМО, почтовый индекс.

image-loader.svg

Импорт и частичное описание структуры.
Всё описанное ниже реализовано в исходниках.

a) Прежде чем начать, проверим zip файл. Убедимся, что он похож на нужный нам и в нём хотя бы есть файлы as_addr_obj… для каждого интересующего нас региона.

Ранее в ФИАС был один файл со всеми регионами, теперь данные о каждом регионе в своей директории.

b) Импортируем файлы AS_ADDR_OBJ_(дата)_(идентификатор).XML, содержащие информацию об адресных объектах.

image-loader.svg

Все элементы однотипные, выбираем только ISACTUAL=1 и ISACTIVE=1. И получить мы можем только название объекта и поля OBJECTID, OBJECTGUID. Теперь в этом файле нет указания на дочерний объект, нет данных об ОКАТО, ОКТМО — все они находятся в отдельном XML файле.

c) Проверим, что OBJECTID является уникальным. Если нет — надо разбираться, что это вызвало и писать в ИФНС. Ранее в ФИАС такая проблема часто возникала. Проиндексируем таблицу по этому полю — по нему будет определяться адресный объект пир обработке последующих XML с данными.

d) Импортируем файлы AS_HOUSES… — дома. Аналогично, интересуют только актуальные записи и дополнительно отсеиваем по типам (дом, здание, строение, корпус). И в этом файле тоже нет данных, какому адресному объекту принадлежит дом.

e) Проиндексируем дома по OBJECTID и убедимся, что все записи уникальны.

f, g) Настало время создать иерархию. Анализируем файлы AS_ADM_HIERARCHY_… и AS_MUN_HIERARCHY_… отбирая только актуальные записи. Пара OBJECTID и PARENTOBJID указывает на OBJECTID объекта.

В этих файлах собрана информация по всем объектам региона. В моём случае PARENTOBJID может быть только адресный объект, но реально в PARENTOBJID может быть и дом. Дочерним у него будет является, например, квартира (файлы AS_APARTMENTS_…).

h) Проиндексируем gar_addr по owner_adm и owner_mun

i) И начнём искать ошибки :) Отметим достижимыми все субъекты РФ. И далее будем отмечать достижимыми все записи, родители которых тоже достижимы, до тех пора, пока количество достижимых не изменится. Так делаем по обоим полям — owner_adm, owner_mun. Если owner_adm = owner_mun = 0, то оказалось так, что мы не можем выбрать этот объект — это ошибка. Информация об этом будет сохранена в отчёте, а запись удалена. Отправляется bug-report

Самизнаетекому

ГАР, полная выгрузка
В файле AS_ADDR_OBJ_20210906_2a908987–3309–454e-9364-b75afd551e12.XML
есть объект с ISACTUAL=»1» ISACTIVE=»1»

однако, его OBJECTID=»95254004» вообще не встречается в AS_ADM_HIERARCHY_20210906_221e769c-cfac-4af6–9a20–04cc9c2e1fe5.XML AS_MUN_HIERARCHY_20210906_214fdb76–13c8–49cf-90ef-b5f05c4ee6df.XML

Таких проблем в выгрузке от 07.09.2021 — 107 (из 1405143+107 записей)

j) Теперь проверяем дома. Удаляем и логируем записи без owner_*, т.к. до них мы не сможем добраться. Логично считать ошибкой отсутствие owner в любом из типе устройств — дом же есть, значит до него надо как-то добраться. Разбираться с такими ситуациями придётся вручную (аналогично предыдущему пункту).

В выгрузке от 07.09.2021 — по owner_adm все дома достижимы; по owner_mun — 1639 домов (из 25842972 интересующих) не имеют владельца.

Надеяться, что дом обычно расположен на конкретной улице и owner_adm должен совпадать с owner_mun не получится. Крайне малое количество домов имеют разных владельцев, например один и тот же дом «Х»:
Башкортостан, Уфимский р-н, Зубовский с/с, д. «Х»
Башкортостан, Уфимский м.р-н, с.п. Зубовский сельсовет, тер. СНТ Авиатор, ул N1, д. «Х»

В выгрузке от 07.09.2021 — не совпадающих owner_adm и owner_mun всего 2231 объект и есть огромное желание пренебречь одним из столбцом owner_*.

k) Настало время заполнить OKATO, OKTMO и KLADR. Информация о них в файле AS_ADDR_OBJ_PARAMS_… и надо выбрать VALUE из актуальных записей соответствующего TYPEID (6,7,11). Какие данные ещё есть в этом файле указано в AS_PARAM_TYPES_…XML

image-loader.svg

Всё просто. Из плюсов, что при обработки иерархии мы не знаем к какому объекту относится OBJECTID — здесь же всё однозначно, искать надо только по таблице addr.

l) Аналогично собираем данные OKATO, OKTMO, POSTALCODE для домов. Это уже другой файл — AS_HOUSES_PARAMS_… с аналогичной предыдущему структурой.

m) Удаляем вспомогательные столбцы и индексы

n, o) Выполняем слияние всех таблиц по регионам в одну общую.
p) Создаём нужные индексы
q) Переименовываем временные таблицы в нормальные имена

Чтобы получить этот результат надо обработать:

XML файлы

Описание

Исходные данные, Гб.

AS_ADDR_OBJ_…

Адресные объекты

0.53

AS_HOUSES_…

Дома

18.77

AS_ADM_HIERARCHY_…

Административно-территориальное и муниципальное устройство. Как минимум один набор необходим.

22.18

AS_MUN_HIERARCHY_…

21.68

AS_ADDR_OBJ_PARAMS_…

Параметры адресных объектов, не обязательно если вам не нужны ОКАТО, ОКТМО

3.74

AS_HOUSES_PARAMS_…

Параметры домов (здесь «спрятаны» почтовые индексы)

61.07

У меня этот процесс занял 28 часов 13 минут.

Приложения:
Исходный код, реализующий импорт. (для Windows; для Linux придётся переписать bat на *sh и команды извлечения файла из архива — поискать exec в php файлах).

P.S.

MySQL dump — только адресные объекты (67Мб).
Вероятно, в дальнейшем дамп будет удалён — потеряет свою актуальность; формат, используемый мной, изменится. Обычно информацию по домам и их индексам я группирую по владельцам — что позволяет уменьшить размер БД до 400Мб и использовать её даже на слабых VDS.

image-loader.svg

P.P. S. locdb.ru давно не обновлялся, но, надеюсь, скоро выложу актуальную базу. «Живых» населённых пунктов стало значительно больше: не только не менее 1000 жителей, также учитываются населённые пункты с большим количеством домов.

© Habrahabr.ru