May 5, 2024

Создание слоя: загрузка данных

В прошлом уроке мы с вами поднимали данных Postgres в контейнере. Если вы забыли или пропустили, рекомендую вернуться и освежить знания.


Мы с вами уже знаем, что для создания слоя необходимо иметь геометрию.

Но у нас же ничего нет... Где нам ее взять??

И на такой вопрос есть решение. Мы с вами рассмотрим самую популярную задачу - загрузку OpenStreetMap (OSM) в свою базу с дальнейшим выводом на карту.


Что нам потребуется?

Подготовка базы данных

Первое, что нам необходимо сделать - создать отдельную базу данных с отдельным пользователем, чтобы отделить OSM от всех остальных данных.

На прошлом занятии мы уже подключились к базе данных с помощью pgAdmin. С этого места и продолжим наш путь джедая котика.

Создаем нового пользователя

  1. Открываем наш сервер и кликаем ПКМ по Login/Group roles => Create => Login/Group Role... (рис 1.)
  2. Указываем имя нашего пользователя. У меня это будет osm (Рис 2.)
  3. На вкладке Definition указываем пароль и не забываем его запомнить/записать (Рис 3.)
  4. На вкладке Privileges ставим ползунок напротив Can login (Рис 4.)
Рис 1. Меню создания нового пользователя
Рис 2. Вводим имя пользователя
Рис 3. Указываем пароль
Рис 4. Даем права

Создаем базу данных

Теперь пришло время создавать наше хранилище данных.

  1. Кликаем ПКМ по Databases (Рис 5.)
  2. Указываем основные параметры (Рис 6.)
    1. Имя базы данных - у меня это osm
    2. Owner - владельцем нашей базы ставим созданного пользователя
  3. Для работы с геометрией обязательно необходимо поставить расширение postgis
    1. Раскрываем нашу базу
    2. Кликаем ПКМ по Extensions => Create => Extension... (Рис 7.)
    3. В списке наименований выбираем posgis (Рис. 8)
Рис 5. Вызов меню создания базы
Рис 6. Установка основных параметров
Рис. 7 Вызов меню добавления расширения
Рис 8. Добавляем расширение postgis

Котик, база готова. Что же дальше?

А дальше мы будем заливать данные!


Первое, что нам потребуется - скрипты для загрузки и файл. Я уже подготовил загрузчик. Сегодня мы посмотрим, как же его использовать.

Загрузчик сделан на базе утилиты osm2pgsql. Что же это за штука такая чудесная? Osm2pgsql позволяет без особых усилий и больших страданий загружать данные OSM в базу postgres.

А теперь поехали загружать.

Нам необходимо склонировать репозиторий в любую удобную папку.

Далее необходимо собрать docker образ, в котором установлен osm2pgsql. Для этого необходимо выполнить команду и дождаться окончания.

cd ./osm2pgsql && docker build -t osm2pgsql:latest .


Теперь нам необходимо скачать файл с данными. Переходим на сайт и качаем russia-latest.osm.pbf.

Этот файл необходимо положить по пути: repository_path/data/files,

где repository_path - папка, куда был склонирован репозиторий

Теперь настраиваем скрипт.

Открываем файл osm2pgsql/osm2pgsql.sh в любом удобном редакторе и меняем следующие переменные

PG_DATABASE - название базы данных

PG_USER - пользователь, которого мы создавали

PG_HOST - ip адрес postgres. У меня указан host.docker.internal, поскольку один контейнер будет подключаться к другому и все это происходит локально. Если у вас БД где-то на сервере, необходимо подставить свой ip

PG_PORT - порт, на котором запущен postgres

После того, как все нужные операции были проделаны, остается самое интересное - запустить.

Из папки с репозиторием выполняем следующую команду

sh osm2pgsql/osm2pgsql.sh

Терминал запросит пароль. Необходимо ввести пароль от пользователя, которого создавали.

Внимание! При вводе пароля символы видно не будет. Учтите это.

Если все сделано верно, то вы должны увидеть следующую картину:

Запуск процесса загрузки данных

На этом моменте вы можете пойти гулять, играть, пить чай. В общем, все, что душе угодно.

Данный процесс может занимать от до 8ми часов.



Надеюсь вы уже вернулись...

По окончанию работы скрипта у нас должна быть следующая картина

Окончание работы скрипта

На этом моменте работа со скриптом будет закончена и можно вернуться в базу данных.


Открываем нашу БД и смотрим на таблички. Должно быть 9 таблиц. Если у вас не видно таблиц, то можно нажать на схему public ПКМ и выбрать пункт Refresh.

Давайте заглянем в какую-нибудь табличку, например, planet_osm_roads.

Выбираем ее ЛКМ и кликаем на кнопку с иконкой таблицы вверху.

Перед нами открылось что-то странное и непонятное, похожее на Excel. Без паники!

Сейчас нас интересует одна единственная колонка.

Если мы пролистаем вправо до самого конца, то обнаружим колонку way и что-то непонятное в данных. Это и есть наша геометрия! Ураааа!

Мы можем выделить колонку и посмотреть геометрию на карте прям из pgAdmin. Для этого нажимаем на заголовок, чтобы выделить все строки, а затем в заголовке жмем на кнопку с иконкой карты.

О, чудо!

Но, подождите, а почему все белое???

Давайте посмотрим.

Сейчас я покажу немного магии postgis.

Чтобы добавить подложку на эту карту, проекция у геометрии должна быть EPSG:4326 и никакая другая. Давайте это проверять.

Выполним запрос

SELECT way, ST_SRID(way), ST_ASGeoJSON(way)::jsonb FROM public.planet_osm_roads
LIMIT 10

Немного поясню, что сейчас произошло.

На первых уроках я показывал и рассказывал про GeoJSON. В postgis есть функции для работы с данным форматом. Одну из таких мы сейчас и использовали - ST_ASGeoJSON.

Данная функция позволяет показать геометрию в формате GeoJSON.

Тут нам уже наглядно видно две вещи:

  1. Если смотреть параметр crs, то видно проекцию EPSG:3857
  2. Более опытный человек может взглядом на координаты понять, что за проекция (это нарабатывается только насмотренностью)

Следующая функция - ST_SRID.

Если мы не хотим смотреть на координаты, то проекцию можно посмотреть, использовав данную функцию.

Итак, мы убедились, что наша проекция не соответствует требованию о наличии EPSG:4326.

Что будем делать?

Предлагаю не модифицировать данные, а создать на основе них представления (views, вьюхи), в которых как раз перепроецируем геометрию.

View представляет собой таблицу с данными, построенными на основе других данных. То есть мы можем выполнить запрос, собрать данные, а в случае изменения исходной таблицы, View автоматически пересчитается.

Переходим к созданию вьюхи. Выбираем ПКМ Views => Create => View...

Указываем имя. У меня это v_planet_osm_roads.

Указываем владельца - созданный нами пользователь.

Переходим на вкладку Code. Здесь нам нужно вставить запрос, которым будет формироваться view.

Вставляем следующий код

SELECT 
	ST_Transform(way, 4326) as geometry
FROM public.planet_osm_roads

И сохраняем.

ST_Transform позволяет трансформировать геометрию из одной проекции в другую. В данном случае мы трансформируем геометрию из поля way с проекцией 3857 в 4326.

Важно учитывать, что для ST_Transform необходима установленная у изначальной геометрии проекция. Бывают моменты, когда у геометрии нет четко проставленной проекции. В таком случае трансформация будет ругаться.

Чтобы решить такой вопрос, может потребоваться выполнение двух функций одновременно. Вторая функция ST_SetSRID(geometry, proj). Она позволяет указать, в какой проекции находится геометрия.

Выполняя ST_Transform(ST_SetSRID(geometry, proj1), proj2) получаем нужный результат.

Теперь давайте посмотрим, что получилось. View смотреть можно точно так же, как и обычную таблицу.

Мы видим таблицу, состоящую из одной колонки.

Попробуем посмотреть геометрию.

Вуаля! У нас есть подложка!

А теперь немного волшебства

Все это круто - таблички, геометрии, какие-то поля, но пока это мало чего нам дает.

Ловите связь.

Вспоминаем формат GeoJSON.

Мы с вами знаем, что для описания объекта нам необходим тип Feature, properties и геометрия. Геометрия у нас есть, тип тоже, а где properties?

Если мы выполним запрос

SELECT way, name, population, boundary FROM public.planet_osm_roads 

то увидим табличку из 4 полей, где way - геометрия, а остальные - набор данных. Так вот, наш набор данных - это и есть properties. То есть мы можем представить представить объект в виде

Поле way переехало в geometry, остальные поля уехали в properties, где ключ - наименование поля, значение - значение из строки.

Таким нехитрым способом мы получили описание объекта.

Для описания слоя нам потребуется уже более верхоуровневая сущность - FeatureCollection. Она содержит в себе массив features - объектов.

Ой, так получается, что таблица в БД соответствует слою?

Да, верно!

Вот мы и создали наши первые слои. А что с этим делать дальше, я покажу в следующих уроках.