Тип данных пространственных объектов

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

MatrixDB использует расширение PostGIS для поддержки пространственных типов данных.

Примечание: Эта функция доступна только в корпоративной версии.

1. Установка PostGIS

Установите RPM-пакет на каждом узле (PostGIS зависит от geos39, поэтому сначала установите зависимости):

sudo yum install https://ftp.postgresql.org/pub/repos/yum/common/redhat/rhel-7-x86_64/geos39-3.9.1-1.rhel7.x86_64.rpm
sudo yum install mxdb-postgis-2.5-1.el7.x86_64.rpm

Подключитесь к базе данных и создайте расширение:

CREATE EXTENSION postgis;

2. Использование PostGIS

2.1 Обычные пространственные типы данных PostGIS

PostGIS поддерживает следующие распространённые типы данных:

  1. POINT (точка)
  2. LINESTRING (линия)
  3. POLYGON (многоугольник)

2.1.1 Создание таблиц

Создайте таблицу, включающую пространственные типы данных:

-- Point table
CREATE TABLE global_points (
    id INT,
    name VARCHAR(64),
    location GEOGRAPHY(POINT)
)
Distributed by(id);

-- Face table
CREATE TABLE global_areas (
    id INT,
    name VARCHAR(64),
    area GEOGRAPHY(POLYGON)
)
Distributed by(id);

2.1.2 Вставка данных

Вставка данных точки:

INSERT INTO global_points VALUES(1, 'point1', 'POINT(-110 29)');
INSERT INTO global_points VALUES(2, 'point2', 'POINT(-111 30)');

Вставка данных многоугольника:

INSERT INTO global_areas VALUES(1, 'area1', 'POLYGON((-100 25, -100 30, -120 30, -120 25, -100 25))');
INSERT INTO global_areas VALUES(2, 'area2', 'POLYGON((-90 25, -90 30, -100 30, -100 25, -90 25))');

2.1.3 Распространённые функции пространственных вычислений

Вычисление расстояния между координатами точек:

SELECT name, ST_Distance('POINT(-110 30)'::geography, location) FROM global_points;
  name  |   st_distance
-------+------------------------------
 point1 | 110844.074057415
 point2 |  96485.974080553
(2 rows)

Вычисление площади:

SELECT id,name,ST_Area(area) FROM global_areas ;
 id | name  |      st_area
----+-----------------------------------------------------------------------------------------------------------------------------
  1 | area1 | 1098617743576.8588
  2 | area2 | 547807626660.82526
(2 rows)

Определение, находится ли точка внутри многоугольника:

SELECT a.name, p.name FROM global_points AS p, global_areas AS a WHERE ST_Intersects (a.area, p.location);
 name  |  name
------+---------------------------------------------------------------------------------------------------------------------------
 area1 | point1
 area1 | point2
(2 rows)

Вычисление пересечения поверхностей:

SELECT ST_AsText(ST_Intersection(a1.area, a2.area)) FROM global_areas as a1, global_areas as a2 WHERE a1.name = 'area1' AND a2.name = 'area2';
st_astext
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 LINESTRING(-100 24.9999999999992,-100 29.9999999999995)
(1 row)

2.2 Создание пространственного индекса

Для эффективности пространственных вычислений пространственные данные должны быть проиндексированы. PostGIS поддерживает следующие типы пространственных индексов:

  1. GIST: Дерево общих запросов (General Query Tree)
  2. BRIN: Индекс блочных диапазонов (Block Range Index)
  3. SP-GiST: Дерево пространственного разделения общих запросов (Spatial Partitioning General Query Tree)

Создание индекса для поля location:

CREATE INDEX global_points_gix ON global_points USING GIST ( location );

Создание индекса для поля area:

CREATE INDEX global_areas_gix ON global_areas USING GIST ( area );