Создание слоя: хранение гео данных
В предыдущих статьях я обмолвился, что мы будем хранить данные в БД Postgres. Почему именно он? На самом деле, все просто до безумия - самая распространенная БД, очень сильно себя зарекомендовавшая. Postgres используют многие, поэтому не вижу никаких причин его не использовать.
Чем же мы сегодня будем заниматься?
- Вспомним немного теории баз данных
- Посмотрим, что нам будет помогать в хранении и обработке гео данных
Немного теории БД
PostgreSQL - это мощная реляционная база данных с открытым исходным кодом бизнес-уровня. Она позволяет использовать реляционные SQL и нереляционные JSON данные и запросы.
Я думаю, все прекрасно знают, что реляционная модель предусматривает единственный способ представления данных – в виде набора двумерных таблиц.
Основные понятия, которыми будем оперировать
Если вы не читали статью про форматы данных, рекомендую сначала вернуться к ней
Из чего состоит таблица? Вы скажите, что все просто - колонки и строки. И да, вы окажитесь правы, но я есть другие понятия - поля (они же атрибуты) и кортежи.
Поля или атрибуты - описание колонок таблицы. Они состоят из описания
- Типа данных
- Признака обязательности - может ли быть пустым поле
- Длинна значения, если тип данных позволяет ограничить
- Признак главного ключа (primary key)
- Признак внешнего ключа (foreign key)
Есть еще ряд параметров, но нам хватит и этого 🙃
Ключи какие-то нам тут даешь... Какие двери ими открывать?
Главный ключ (он же primary key) обычно вешается на поле с идентификатором объекта. С его помощью можно однозначно идентифицировать, какой перед нами объект.
Primary key может быть несколько. Такое явление называется составным ключом. На практике именно в ГИС я такого не наблюдал, но, если понадобится, разберемся детально в процессе.
Внешний ключ (foreign key) обычно служит для связи двух таблиц между собой. Обычно в него записывают значение primary key другой таблицы. Таких ключей может быть несколько в рамках одной таблицы.
Установка признака внешнего ключа влияет на консистентность данных. Иными словами, если не проставить этот признак, то в поле можно будет записать индетификатор, которого не существует в связной таблице.
Например. Предположим, мы решили организовать склад хранения колес. Для этого нам необходимо иметь данные об автомобиле и его владельце, а также при приеме колес на хранение нужно учитывать ряд параметров - радиус колеса и тд. В этом случае можно схему БД можно представить следующим образом:
Получается, владелец (owners) может иметь несколько автомобилей. У автомобилей (cars), как мы знаем, по 4 колеса (wheels). Везде получается связь 1 ко многим.
Кортежем является строка таблицы, содержащая данные по полям.
Ну и зачем же ты нам это рассказываешь?
Следите за ходом мысли!
Немного вернемся к самой первой статье и вспомним, что такое объект с точки зрения картографии.
Объект - сущность, содержащая в себе геометрию и ее атрибутивный состав. Объект без геометрии существовать не может.
Из этого определения мы можем сделать вывод, что:
- Для того, чтобы у нас был именно картографический объект, необходимо иметь поле типа Geometry
- Атрибутивный состав объекта - набор полей таблицы
А получается интересная штука.
Слой получается путем создания таблицы, одним из полей которой является геометрия. С точки зрения GeoJSON, таблицу можно представлять в виде FeatureCollection, каждый кортеж которой - Feature, а поля таблицы попадают в properties.
Иными словами, в 90% случаев одна таблица в БД соответствует одному слою.
Бывают исключения. Например, мы хотим, чтобы на один объект приходилось несколько геометрий, каждая из которых могла быть стилизована по-своему.
В таком случае разумно будет создать две таблицы и связать их между собой в отношении 1 ко многим, либо использовать GeometryCollection и JSON поле с массивом атрибутов для геометрий.
Если мы будем делать несколько таблиц, то нам придется их все равно соединить в одну таблицу (создать представление (view) данных), где будет дублирование информации. Можно обойтись без представления, поскольку Geoserver'у можно скормить SQL, в котором прописать связь. На мой взгляд, это не самый удачный вариант, потому что можно забыть об этом SQL, изменить таблицу в бд, а потом сидеть и гадать, почему же у меня слой перестал выводится или что-то не отображается.
Как хранить гео данные в Postgres?
Вы можете задаться вопросом, а как же хранить гео данные, если Postgres по-умолчанию не умеет?
Вы всегда можете воспользоваться вариантом JSON полей, куда прописывать GeoJSON, но это не наш случай. В нашем варианте мы будем рассматривать расширение PostGIS.
PostGIS — программное расширение с открытым исходным кодом, расширяющее пространственную базу данных системы управления PostgreSQL. Расширение добавляет поддержку географических объектов, благодаря чему появляется возможность выполнять запросы местоположения в SQL.PostGIS позволяет хранить ряд географических и пространственных данных — точек, ломаных линий, полигонов, растр, а также использовать их для разных операций, например, поиска.
PostGIS в PostgreSQL используется для снятия ограничений, расширения функций и позволяет применять:
- растровые данные;
- функции создания геометрий и управления ими (создание и удаление полей с географическими данными, запросы скриптов, библиотек);
- функции редактирования геометрий и их форматированного вывода;
- расширенные 2D- и 3D-функции, в том числе для определения пересечений в 3D-пространстве);
- инструменты для определения пространственных отношений и измерений (например, для сравнения расстояния по плоскости и на сфере);
- функции создания и отображения растров в удобном формате (например, в JPEG или PNG);
- инструменты обработки растров (очищение рельефа, векторизация, увеличение или уменьшение яркости).
Возможности связки PostGIS и PostgreSQL на практике могут использоваться для определения:
- расстояния от точки до точки;
- ближайшей точки между извилистыми улицами на местности;
- улицы или даже дома по определенным координатам;
- количества домов, попадающих в заданную область пространства;
- количества объектов, находящихся поблизости с заданной точкой;
- площади, расстояний, длин, периметров заданных объектов и множества других данных.
Например, PostgreSQL с предустановленным расширением PostGIS может использоваться для:
- вычисления площади города, региона, государства;
- поиска ближайшей кофейни или магазина;
- построения карты (в том числе растровой) с отображением заданных объектов;
- поиска объектов или местностей, отвечающих заданным критериям (самый крупный город, самая южная страна, самая высокая точка).
Именно благодаря нему у нас и появляется возможность создавать поля с типом Geometry.
Все возможности PostGIS описывать не буду, иначе это будет долго и очень много. Будем разбирать на практике, быстрее поймете 🙃
Поскольку нам предстоит изучение довольно большого объема информации, я решил поделить эту статью на несколько частей.
В следующей части мы коротко пробежимся о том, что такое контейнеризация и docker, а также запустим Postgres с установленным PostGIS.