Что такое родительский объект в фиас
Введение
Адреса официальной публикации:
Оба источника предлагают идентичные данные.
Федеральная информационная адресная система (ФИАС) создана Распоряжением Правительства Российской Федерации от 10.06.2011 №1011-р. С целью.
С момента первой публикации структура и содержание ФИАС многократно критиковались. Тем не менее, за время существования базы, она объективно улучшается и часть ошибок уже устранена. Поэтому указанные в этом документе несоответствия могут быть исправлены в будущем и их следует уточнять на свежих данных.
Загрузка данных
Процесс импорта данных из файлов XML в реляционную базу данных дается на примере PostgreSQL. Все применяемые инструменты являются кросплатформенными. Для других БД (MySQL, Oracle и т.п.) процедура потребует незначительной доработки. См. также гл. 2.3, в которой приводятся ссылки на сторонние проекты, предоставляющие подготовленные данные в других форматах.
Создание таблиц
На сайте ФИАС представлены схемы XSD, описывающие структуру данных. Для преобразования схемы в формат SQL (CREATE TABLE. ) применим XSL Transformation (XSLT). В зависимости от БД может потребоваться изменить типы данных колонок.
Далее, полученные файлы SQL желательно откорректировать, чтобы явно назначить ключи (primary keys).
//// Ссылка на готовые файлы
Импорт данных
Ниже приводится скрипт ETL Scriptella (Apache License) на базе парсера SAX. Он подходит для любой реляционной БД, для которой есть java-драйвер.
Другие источники
Данные ФИАС также распространяются в формате DBF. Для работы с ними рекомендуются утилиты типа PgDBF (импорт ФИАС).
Структура данных ФИАС (описание таблиц)
Для понимания структуры данных ФИАС требуются следующие документы:
Таблицы
ADDROBJ
Текстовые элементы адреса
Поле FORMALNAME создано специально для поиска: из него исключены все нестандартные символы и знаки пунктуации, буква «ё» заменена на «е» и т.п. Все записи удовлетворяют запросу:
Иерархия административных единиц
В таблице ADDROBJ иерархия построена по типу плоского дерева. И родительские и дочерние элементы хранятся в одной таблице. Воссоздание иерархии выполняется с помощью полей:
Получение полного адреса (от младшего к старшему):
AOLEVEL отражает административно-правовое подчинение, поэтому одни и те же текстовые элементы адреса могут располагаться на разных уровнях. Например, в снт. «Волжанка» (AOLEVEL=90) улицы имеют уровень 91 (против более распространенного 7):
(1) обл. Самарская (3) р-н Сызранский (90) снт Волжанка (91) ул. Ягодная (91) ул. Дачная (91) ул. Рябиновая
Аналогично, существуют населенные пункты без улиц. Например, в пос. Лужки иерархия заканчивается на уровне 6:
(1) обл. Орловская (3) р-н Мценский (6) п. Лужки
Таким образом, построение таблицы полных адресов следует начинать от верхних элементов (AOLEVEL=1) к нижним (AOLEVEL=91), как правило, запрос оформляется в виде множества подзапросов (subquery). Или рекурсивно подниматься от нижних, не имеющих дочерних элементов. Рассмотрим для примера второй вариант. Поскольку число полей в обоих случаях не определено, то полный адрес будет формироваться единой строкой:
Статус актуальности
Из базы ФИАС почти никогда не удаляются элементы. Они могут быть только переведены в разряд «отключенных» (устаревшие, измененные и т.п.), что аналогично работе КЛАДР.
Рассмотрим поля, определяющие действительность объекта:
Покажем на примере выбор актуальных и исторический записей. «Пермский край» был образован 01.12.2005 объединением «Пермской области» и «Коми-Пермяцкого АО». В базе ФИАС это отразилось следующим образом (см. табл. 1):
Примечание | Актуальная запись | Пермская обл. | Коми-Пермяцкий АО |
AOID | c685f6ca-d7e1-4938-8b21-7c20035652d2 | 744e2599-d2bb-4364-9922-c13febb16e81 | 68824dc3-da0f-42d3-bd0b-1ceb91ff27bf |
AOGUID | 4f8b1a21-e4bb-422f-9087-d3cbf4bebc14 | 4f8b1a21-e4bb-422f-9087-d3cbf4bebc14 | e3d95b95-cc2d-440d-95c6-65577fae076e |
AOLEVEL | 1 | 1 | 1 |
PREVID | 744e2599-d2bb-4364-9922-c13febb16e81 | 68824dc3-da0f-42d3-bd0b-1ceb91ff27bf | |
NEXTID | c685f6ca-d7e1-4938-8b21-7c20035652d2 | 744e2599-d2bb-4364-9922-c13febb16e81 | |
ACTSTATUS | 1 | 0 | 1 |
OPERSTATUS | 1 | 1 | 1 |
CURRSTATUS | 0 | 1 | 51 |
LIVESTATUS | 1 | 0 | 0 |
UPDATEDATE | 2011-09-13 | 2011-09-13 | 2011-09-13 |
STARTDATE | 1900-01-01 | 1900-01-01 | 1900-01-01 |
ENDDATE | 2079-06-06 | 2079-06-06 | 2079-06-06 |
FORMALNAME | Пермский | Пермская | Коми-Пермяцкий |
OFFNAME | Пермский | Пермская | Коми-Пермяцкий |
SHORTNAME | край | обл | АО |
Исторические названия
В общем виде получение исторических вариантов наименований объекта имеет вид:
shortname | formalname | actstatus | operstatus | currstatus | livestatus | updatedate | startdate | enddate |
д | Малое Пермиево | 1 | 21 | 0 | 1 | 2012-09-08 | 2012-02-01 | 2079-06-06 |
д | Малое Пермиево | 0 | 1 | 2 | 0 | 2011-09-14 | 1900-01-01 | 2012-02-01 |
с | Малое Пермиево | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
. | ||||||||
ул | Подстанция 220 | 1 | 20 | 0 | 1 | 2012-03-12 | 1911-11-11 | 2079-06-06 |
ул | Подстанция (Комиссарово) | 0 | 1 | 1 | 0 | 2011-09-15 | 1900-01-01 | 1911-11-11 |
. | ||||||||
пер | Рябиновый | 1 | 20 | 0 | 1 | 2011-09-27 | 1900-01-01 | 2079-06-06 |
ул | Рябиновая | 0 | 1 | 1 | 0 | 2011-09-15 | 1900-01-01 | 2079-06-06 |
. | ||||||||
снт | Восход(п.Селезнево) | 1 | 1 | 0 | 1 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
дп | СТ Восход(п.Селезнево) | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
. | ||||||||
ул | Самбуева В.М. | 1 | 1 | 0 | 1 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
ул | Ф.Энгельса | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
. | ||||||||
проезд | 3-й Лабинский | 1 | 1 | 0 | 1 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
ул | Лабинская 2-я | 0 | 1 | 1 | 0 | 2011-09-14 | 1900-01-01 | 2079-06-06 |
Адресные классификаторы
Записи в БД ФИАС содержат ссылки на другие российские адресные классификаторы:
В целом, код является расширенным вариантом КЛАДР:
Могут быть случаи, когда адресному объекту в БД ФИАС не соответствует никакой КЛАДР-код, например:
Подробное описание см. в документе «Сведения о составе информации Федеральной информационной адресной системы».
Прочие поля
Обновление БД ФИАС
На портал ФИАС выгружаются актуальные и исторические сведения ФИАС, а так же технологически удалённые из БД ФИАС адресные сведения. Актуальные и исторические сведения ФИАС выгружается в виде файлов (таблиц) DBF и файлов XML. Вместе с полной базой ФИАС выгружаются дельта данные – новые, изменившиеся и удаленные данные с момента предыдущей выгрузки базы. Дельта данные, т.е. новые, изменившиеся и удаленные данные появившиеся с момента предыдущей выгрузки базы ФИАС, загружаются по следующему алгоритму: по наличию или отсутствию ключа в пользовательской базе определяется тип операции – добавление или обновление записи. После проведения соответствующих операций необходимо удалить по ключу записи, присутствующие в таблицах технологически удаленных данных.
Наличие таких «дельт» позволяет быстро обновить БД ФИАС, не скачивая полный архив (на 2014.12.01 его размер составляет 1.8 Гб). Алгоритм обнобления, действительно, довольно прост. Привожу текст процедуры обновления для MySQL на примере таблицы ADDROBJ:
Иногда может изменятся структура самих таблиц, что требует ручного контроля. Например, колонка «oktmo» сначала содержала 8 символов, а потом была расширена до 11 символов.
Ошибки БД ФИАС
БД ФИАС может содержать ошибки в данных, а) связанные с нарушением целостности двунаправленных списков PREVID/NEXTID, б) ошибки, когда запись об адресном объекте имеет OPERSTATUS = 1, а в действительности произошла другая операция (переименование, переподчинение, слияние, или дробление), и в) ошибки, когда отсутствуют исторические сведения (вызванные тем, что администраторы БД ФИАС, видимо, выполняли прямое изменение данных с помощью SQL-запросов).
Для иллюстрации можно открыть портал ФИАС и воспользоваться расширенным поиском. В поле «Регион» введите «Санкт-Петербург город», в поле «Уровень» выберите «Регион». Нажмите «Найти». Если просмотреть историю изменения города Санкт-Петербург, то можно обнаружить, что Санкт-Петербург раньше назывался «станция Володарская», а должно быть «Ленинград». Это иллюстрирует нарушение целостности двунаправленных списков.
Для иллюстрации ситуации, когда отсутствуют исторические сведения можно рассмотреть адресный объект с AOGUID=»df84b14c-6006-46d1-8ce3-3a6ddf8643bd». В БД ФИАС от 2012.08.06 этот объект имел КЛАДР код равный 24000001101000100. В какой-то момент произошло переподчинение родительского объекта, и в итоге у него изменился уровень AOLEVEL с 6 на 90. Соответственно, уровень AOLEVEL дочернего объекта изменился с 7 на 91. Если взять БД ФИАС от 2014.12.01, то в ней нельзя обнаружить исторической записи с КЛАДР кодом равным 24000001101000100. Нет этой записи и в таблицах DADDROBJ.
Ошибки с неправильным OPERSTATUS слишком многочисленны, их классифицирование выходит за рамки данной статьи.
Дома ФИАС в среде PostgreSQL
Предыдущая статья с описанием адресов ФИАС и функций для работы с ними в среде PostgreSQL вызвала интерес у небольшой части читателей.
Поэтому имеет смысл описать аналогичные функции на языке PL/pgSQL для работы со списком домов ФИАС, загруженным в базу данных под управлением PostgreSQL.
Родословная дома
Вызов функции fstf_Houses_AddressObjectTree (‘42301ab8-9ead-4f8e-8281-e64f2769a254’) приведет к получению следующего списка записей.
Таблица 1. Результат выполнения функции.
При внимательном рассмотрении можно заметить, что в качестве аргумента функции передан идентификатор элемента (HOUSEGUID) «д. 1, корп. 2, стр. 26», в результате получены шесть записей:
У функции есть еще один необязательный параметр — дата окончания действия записи (EndDate), с помощью которого можно просматривать родословную не только актуальной записи о доме, но и уже устаревших записей.
Полный текст функции приведен в Приложении в подразделе Создание функции fstf_Houses_AddressObjectTree.
С самого начала
Если вы знаете как устроена таблица домов ФИАС, то этот раздел можно пропустить.
Дома ФИАС (HOUSES) представляют собой дочерний список для списка адресообразующих элементов ФИАС (ADDROBJ). Каждая запись списка домов ссылается на адресообразующий элемент ФИАС значением поля AOGUID. Для того чтобы определить на какой улице и в каком населенном пункте находится дом нужно по значению AOGUID записи HOUSES найти соответствующую запись с таким же идентификатором списка ADDROBJ.
При всей внешней простоте механизма взаимодействия списка домов со списком адресообразующих элементов в их взаимодействии особенности, осложняющие реализацию функций на HOUSES.
Во-первых, каждая запись списка домов по идентификатору AOGUID ссылается на группу адресообразующих элементов, один из которых является актуальным.
Во-вторых, в списке ФИАС несколько записей с одним и тем же набором характеристик номера дома: номер дома, номер корпуса, номер строения.
В-третьих, запись о доме не всегда наследуется от записи об улице населенного пункта.
Но, обо всем по порядку.
Для дальнейшего рассмотрения хранения сведений о домах в ФИАС достаточно ограничиться на 4 таблицах (DBF-файлах):
ADDROBJ подробно рассмотрена в предыдущей публикации «Адреса ФИАС в PostgreSQL», поэтому здесь о ее особенностях будет говорится ровно столько, сколько необходимо для описания характеристик домов.
Таблица 2. История дома «Красноярский край, р-н Таймырский Долгано-Ненецкий, г Дудинка, ул. Дудинская, д. 1»
Как видно из таблицы, в отличии от адресообразующих объектов, записи истории дома не имеют специальных признаков актуальности. Актуальной является запись с самой старшей датой окончания периода, которая больше текущей. Пока актуальные записи о домах помечаются датой «06.06.2079». Все остальные записи о доме считаются историческими, а даты начала и окончания характеризуют период актуальности каждой записи.
Список домов ФИАС не содержит указателей на предыдущую и следующую записи о доме. Поэтому порядок следования записей от актуальной в глубь истории дома определяются по убыванию даты окончания и за ней даты начала периода, соответственно EndDate и StartDate.
Внимательный читатель, глядя на Рис. 1, наверняка задал себе вопрос: зачем упомянуты справочники признаков строения и владения? В ФИАС используется свыше 10 подобного рода справочников, так почему особо выделены эти два?
Ответ многих удивит – с точки зрения «логики ФИАС» адрес дома не полностью идентифицируется адресом улицы, номерами дома, корпуса и строения. Термин «логики ФИАС» использован в ответе сотрудника ФНС на мой вопрос почему в списке домов Красноярского края находится свыше 250 парных адресов домов. В этом же ответе было сказано, что уникальность записи обеспечивают значения AOGUID, HOUSENUM, BUILDNUM, STRUCNUM, STRSTATUS, ESTSTATUS.
Другими словами, для нахождения объекта недостаточно знать населенных пункт, улицу, номер дома. Необходимо еще знать:
Вот так выглядит выборка из общего списка домов ФИАС с повторяющимися адресами.
В том, что разные объекты имеют одинаковый адрес нет ничего удивительного. Здание и земельный участок под ним; дом, гараж, баня у одного хозяина. Все они имеют один и тот же адрес. Но ФИАС – это адресный реестр, т.е. список адресов. Поэтому естественно ожидать, что уникальными в нем будут адреса, а не здания, строения, сооружения.
Т.е. список домов ФИАС из списка адресов домов начал развиваться в сторону перечня наземных строений. И пользователям ФИАС необходимо это учитывать.
Каждый желающий может сам проверить наличие домов с повторяющимися адресами, выполнив оператор SELECT подобный следящему. При этом, функцию fsfn_Houses_TreeActualName можно не применять, т.к. она использована только для того, чтобы сократить число колонок результата. Не обязательно использовать справочники fias_StructureStatus (аналог STRSTAT) и fias_EstateStatus (аналог ESTSTAT), т.к. отмеченный эффект можно проследить и на кодах признаков строения и владения.
И наконец, еще одна особенность списка домов ФИАС. Каждая запись о доме этого списка содержит ссылку на адресообразующий элемент, список которых представляет собой иерархию таких элементов. На каждом уровне иерархии находятся адресообразующие элементы, относящиеся к различным типам. Так корневым элементом является регион (Красноярский край в нашем случае), на следующем уровне автономный округ, район или город регионального подчинения. И так далее. (Подробности смотри в «Адреса ФИАС в PostgreSQL»).
Формально запись о доме позволяет ссылаться на элемент иерархии любого уровня. К счастью, домов, ссылающихся на район или регион, среди данных Красноярского края не встретилось. И тем не менее не все дома ссылаются на улицу населенного пункта:
Размножение адресов дома по владельцам (ФИАС vs карта)
Здесь описана проблема, которая приводит к неоднозначному толкованию родословной дома. (На эту проблему мое внимание обратил Игорь Леонидович Тимощенков, ГИС-специалист, компании ООО «Айгео», Красноярск).
Выше показано как несколько записей содержат один и тот же адрес дома. Что можно объяснить желанием налоговой инспекции хранить не только запись о частном доме, но и об окружающих постройках: гараже, сарае, и т.д. Но есть обратные примеры, когда одному строению (дому) соответствуют несколько записей таблицы fias_Houses с различными значениями номеров этого дома.
Вглядитесь в этот рисунок. Слева на нем снимок экрана с картой поселка, где расположены домами на два хозяина. Это обычные одноэтажные дома с двумя входами. Справа живет одна семья, а слева другая. Их еще можно представлять, как дома из двух квартир.
А теперь посмотрите на таблицу справа. В ней практически каждому дому на два хозяина соответствует по 3 записи. Т.е. таблице домов ФИАС указаны как адрес отдельного дома («д. 1»), так и адреса частей дома («д. 1/1», «д. 1/2»), принадлежащих одному хозяину.
Как это работает
Функция fstf_Houses_AddressObjectTree имеет две версии: с четырьмя или с двумя параметрами. В версии функции с двумя параметрам передается идентификатор дома (HouseGUID) и дата окончания действия записи (EndDate). Версия с четырьмя параметрами дополнительно требует идентификатор адресообразующего элемента (AOGUID) и текущий статус (CurrStatus).
Функция с меньшим числом параметров вычисляет значения недостающих параметров и вызывает функцию с большим числом параметров. Для этого предварительно идентификатор адресообразующего элемента просто извлекается из соответствующего поля таблицы домов (fias_Houses). А значение текущего статуса (CurrStatus) вычисляется по следующим правилам:
Функция с большим числом параметров сначала вызывает функцию fstf_AddressObjects_AddressObjectTree, которая возвращает родительские адресообразующие элементы для дома. Подробнее о функции fstf_AddressObjects_AddressObjectTree можно прочитать в разделе Родословная адресообразующего элемента документа «Адреса ФИАС в среде PostgreSQL»
Затем записи об адресообразующих элементах дополняются записями о номерах дома, корпуса, строения (см. Таблица 1), которые создаются для каждого непустого поля о номере дома, корпуса и строения.
Для того чтобы все выводимые записи имели одинаковую структуру и не без некоторой доли пижонства, в теле функции искусственно создаются значения полей код уровня (AOLevel), текущий статус (CurrStatus) и статус актуальности (ActStatus).
Коду уровня дома (корпуса, строения) всегда присваивается значение 8, смотри справочник «Уровней адресных объектов» из документа Сведения о составе информации ФИАС).
Статусу актуальности присваивается значение 1, если дата окончания действия записи (EndDate) равна 06.06.2079, и 0 в противном случае.
Со значениями поля CurrStatus дело обстоит сложнее. При помощи его значений решаются две задачи одновременно: устанавливается идентификатор каждой версии записи об адресообразующем элементе и присваивается признак актуальности записи. Поэтому последняя актуальная запись об элементе содержит значение 0 в этом поле, а все исторические записи нумеруются в порядке появления – «1» самая ранняя запись, следующая за ней по времени – «2» и т.д. Подробнее порядок присвоения значений полю CurrStatus рассмотрен в публикации «Адреса ФИАС в PostgreSQL».
Полный адрес дома
Основная идея функции fsfn_Houses_TreeActualName в том, чтобы возвратить соединенные в одну строку номер дома вместе с названиями всех его предков – адресообразующих элементов.
Например, пусть функция родословной дома (fstf_Houses_AddressObjectTree) возвращает следующий список значений.
Таблица 4. Результат выполнения функции fstf_Houses_AddressObjectTree(‘0c0d670f-097c-4e1d-bcac-9e9b22fb1b99’)
Тогда fsfn_Houses_TreeActualName (‘0c0d670f-097c-4e1d-bcac-9e9b22fb1b99’) должна возвратить: «г Красноярск, ул им Сергея Лазо, д. 34А, корп. 6, стр. 17».
Функцию fsfn_Houses_TreeActualName упрощенно можно представлять, как агрегатную функцию STRING_AGG над результатом функции, возвращающей родословную дома.
У рассматриваемой функции есть еще одни необязательный параметр — массив масок (a_MaskArray), с помощью которого можно включать в результат не все названия элементов, а только те, которые нужны.
Таблица 5. Список масок функции.
Значение | Примечание |
---|---|
Маска — номер дома | |
Маска — номер корпуса | |
Маска — номер строения | |
Маска — улица | |
Маска — почтовый индекс | |
Маска — городской район | |
Маска — подчиненный населенный пункт | |
Маска — основной населенный пункт | |
Маска — района субъекта федерации | |
Маска — субъект федерации (регион) | |
Маска — страна |
Поиск дома ФИАС
Функция fstf_Houses_SearchByName предназначена для поиска адресов домов ФИАС по их номерам и названиям адресообразующих элементов. При этом поиск может осуществялться не только по названию и типу текущего элемента, но и названиям и типам одного или двух его ближайших предков.
Рассмотрим несколько примеров. И для начала найдем все дома с номером «220».
Таблица 6. Результат выполнения функции fstf_Houses_SearchByName(‘220’)
В отличие от функции поиска адресообразующих элементов (fstf_AddressObjects_SearchByName) результат этой функции не содержит эфекта «плавания» по уровням адресообразующих элементов. Первый параметр функции всегда содержит шаблон поиска номера дома, второй – номера корпуса, третий номера строения.
Теперь изменим запрос. Найдем все дома адресообразующих элементов, номер которых содержит цифру «1», и в названиях встречается слово «Красноярск».
Таблица 7. Результат выполнения функции fstf_Houses_SearchByName(‘1′,NULL,NULL,’Красноярск’)
Назначение остальных параметров в точности совпадает с назначением параметров функции поиска адресообразующих эелементов (fstf_AddressObjects_SearchByName).
Текст функции приведен в разделе Приложения «Создание функции fstf_Houses_SearchByName»
Как это работает
Реализация fstf_Houses_SearchByName во многом похожа на реализацию функции поиска адресообразующих элементов (fstf_AddressObjects_SearchByName). Главное отличие заключается в том, что поиск осуществляется в двух, связанных таблицах fias_Houses и fias_AddressObjects.
У функции 9 аргументов. Первые три из них – это номера дома (a_HouseNum), корпуса (a_BuildNum) и строения (a_StrucNum). Остальные 6 (a_FormalName, a_ShortName, a_ParentFormalName, a_ParentShortName, a_GrandParentFormalName, a_GrandParentShortName) полностью совпадают с параметрами функции.
Если задать только значение параметра «номер дома», то функция возвратит все адреса в номере дома, которых встречаются указанная последовательность символом. Если в качестве номера дома передать значение NULL или пустую строку («»), то будут возвращены адреса всех домов, адресные элементы которых заданы набором прочих параметров.
Эпилог
Этот раздел содержит рекомендации к тому, как загрузить список домов ФИАС в таблицу fias_Houses.
Загрузка данных в таблицу домов выполняется примерно также как загрузка данных в таблицу адресообразующих элементов. Только исходным файлом станет HOUSE99.DBF, а не ADDROB99.DBF. Здесь 99 – это номер региона (Республики, области, края). Например, для Красноярского края исходным является файл HOUSE24.DBF.
Сначала с страницы «Обновления» ФИАС скачивается очередной архив с обновлением. Из него извлекается файл HOUSE99.DBF
Затем файл HOUSE99.DBF преобразуется к формату CSV и уже преобразованный он загружается оператором COPY во временную таблицу fias_Houses_Temp.
И, наконец, данные временной используют для обновления основной таблицы, т.е. несуществующие в fias_Houses добавляются, а уже существующие – заменяются.
Пример скрипта обновления таблицы домов приведен в разделе «Загрузка обновлений домов ФИАС в таблицу fias_Houses».