Как стать автором
Обновить

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

Время на прочтение 6 мин
Количество просмотров 23K

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, но уже целочисленный.

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

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

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

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

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

Все элементы однотипные, выбираем только 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"

<OBJECT ID="1823960" OBJECTID="95254004" OBJECTGUID="e3b0cdce-8a09-4955-8a43-a85ae759cfde" CHANGEID="138210670" NAME="2-й Мартозанова" TYPENAME="пер" LEVEL="8" OPERTYPEID="10" PREVID="0" NEXTID="0" UPDATEDATE="2020-01-15" STARTDATE="2020-01-15" ENDDATE="2079-06-06" 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

Всё просто. Из плюсов, что при обработки иерархии мы не знаем к какому объекту относится 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.

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

Теги:
Хабы:
+6
Комментарии 21
Комментарии Комментарии 21

Публикации

Истории

Работа

PHP программист
175 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн
PG Bootcamp 2024
Дата 16 апреля
Время 09:30 – 21:00
Место
Минск Онлайн
EvaConf 2024
Дата 16 апреля
Время 11:00 – 16:00
Место
Москва Онлайн