API базы данных GeoDjango

Механизмы пространственных баз данных

GeoDjango в настоящее время предлагает следующие механизмы пространственных баз данных:

  • django.contrib.gis.db.backends.postgis
  • django.contrib.gis.db.backends.mysql
  • django.contrib.gis.db.backends.oracle
  • django.contrib.gis.db.backends.spatialite

Пространственные ограничения MySQL

До MySQL 5.6.1 пространственные расширения поддерживали только операции с ограничивающим прямоугольником (то, что MySQL называет «минимальным ограничивающим прямоугольником» или MBR). В частности, MySQL не соответствовал стандарту OGC. Django поддерживает пространственные функции, работающие с реальной геометрией, доступной в современных версиях MySQL. Однако пространственные функции не так богаты, как у других движков, таких как PostGIS.

Изменено в Django 3.0:

Добавлена ​​поддержка пространственных функций, работающих с реальной геометрией.

Предупреждение

Истинные пространственные индексы (R-деревья) поддерживаются только таблицами MyISAM в MySQL. [4] Другими словами, при использовании пространственных расширений MySQL вы должны выбирать между быстрыми пространственными запросами и целостностью ваших данных (таблицы MyISAM не обрабатывают транзакции или ограничения внешнего ключа).

Матричные данные

RasterField в настоящее время реализован только для движка PostGIS. Пространственные запросы доступны для полей матрицы, но не для функций пространственной базы данных или агрегатов.

Создание и сохранение моделей с геометрическими полями

Вот пример того, как создать геометрический объект (при условии, что модель Zipcode существует):

>>> from zipcode.models import Zipcode
>>> z = Zipcode(code=77096, poly='POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z.save()

Объекты GEOSGeometry также можно использовать для сохранения геометрических моделей:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> poly = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))')
>>> z = Zipcode(code=77096, poly=poly)
>>> z.save()

Кроме того, если объект GEOSGeometry находится в другой системе координат (его значение SRID отличается), чем у поля, он будет неявно преобразован в SRID поля модели с использованием процедуры преобразования пространственной базы данных. :

>>> poly_3084 = GEOSGeometry('POLYGON(( 10 10, 10 20, 20 20, 20 15, 10 10))', srid=3084)  # SRID 3084 is 'NAD83(HARN) / Texas Centric Lambert Conformal'
>>> z = Zipcode(code=78212, poly=poly_3084)
>>> z.save()
>>> from django.db import connection
>>> print(connection.queries[-1]['sql']) # printing the last SQL statement executed (requires DEBUG=True)
INSERT INTO "geoapp_zipcode" ("code", "poly") VALUES (78212, ST_Transform(ST_GeomFromWKB('\\001 ... ', 3084), 4326))

Таким образом, параметры геометрии могут быть переданы с помощью объекта GEOSGeometry , WKT (общеизвестный текст [1] ), HEXEWKB (специфичный для PostGIS, геометрический объект WKB в шестнадцатеричном формате [2] ) и GeoJSON (см.RFC 7946 ). Фактически, если данные не являются объектомGEOSGeometry , поле геометрии пытается создать экземплярGEOSGeometry из предоставленных данных.

Для получения дополнительной информации о создании объектов GEOSGeometry см. Учебник GEOSI .

Создание и сохранение моделей с матричными полями

При создании матричных моделей поле матрицы неявно преобразует входные данные в объект GDALRaster путем отложенной оценки. Следовательно, это поле принимает те же данные, что и конструктор GDALRaster .

Вот пример того, как можно создать объект матрицы из файла матрицы volcano.tif (при условии, что модель Elevation существует):

>>> from elevation.models import Elevation
>>> dem = Elevation(name='Volcano', rast='/path/to/raster/volcano.tif')
>>> dem.save()

Объекты GDALRaster также можно использовать для сохранения матричных моделей:

>>> from django.contrib.gis.gdal import GDALRaster
>>> rast = GDALRaster({'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
...                    'scale': [0.1, -0.1], 'bands': [{"data": range(100)}]})
>>> dem = Elevation(name='Canyon', rast=rast)
>>> dem.save()

Обратите внимание, что это эквивалент:

>>> dem = Elevation.objects.create(
...     name='Canyon',
...     rast={'width': 10, 'height': 10, 'name': 'Canyon', 'srid': 4326,
...           'scale': [0.1, -0.1], 'bands': [{"data": range(100)}]},
... )

Пространственные поиски

Типы запросов GeoDjango можно использовать с любым методом в качестве менеджера filter() и exclude() т. Д. Однако типы запросов, специфичные для GeoDjango, доступны только для пространственных полей.

Фильтры для «обычных» полей (например CharField ) могут быть связаны с фильтрами по географическим полям. Географические запросы принимают геометрические и матричные входные данные с обеих сторон, и типы входных данных можно свободно смешивать.

Общая структура географических запросов описана ниже. Полную справку можно найти в справочнике по космическим исследованиям .

Геометрические поиски

Географические запросы с геометрическими объектами имеют следующую общую форму ( Zipcode пример модели, используемый в API модели GeoDjango ):

>>> qs = Zipcode.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Zipcode.objects.exclude(...)

Например :

>>> qs = Zipcode.objects.filter(poly__contains=pnt)
>>> qs = Elevation.objects.filter(poly__contains=rst)

В данном случае poly это географическое поле, contains это тип пространственного поиска, pnt это параметр (который может быть GEOSGeometry объектом или строкой GeoJSON, WKT или HEXEWKB) и rst является объектом GDALRaster .

Матричный поиск

Синтаксис матричных запросов аналогичен синтаксису геометрических форм. Единственное отличие состоит в том, что индекс полосы может указываться дополнительно. Если индекс полосы не указан, 0 по умолчанию используется первая группа (индекс ). В этом случае синтаксис идентичен синтаксису геометрических запросов.

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

Это приводит к следующей общей форме для запросов с использованием матриц ( Elevation пример модели, используемой в API модели GeoDjango )

>>> qs = Elevation.objects.filter(<field>__<lookup_type>=<parameter>)
>>> qs = Elevation.objects.filter(<field>__<band_index>__<lookup_type>=<parameter>)
>>> qs = Elevation.objects.filter(<field>__<lookup_type>=(<raster_input, <band_index>)

Например :

>>> qs = Elevation.objects.filter(rast__contains=geom)
>>> qs = Elevation.objects.filter(rast__contains=rst)
>>> qs = Elevation.objects.filter(rast__1__contains=geom)
>>> qs = Elevation.objects.filter(rast__contains=(rst, 1))
>>> qs = Elevation.objects.filter(rast__1__contains=(rst, 1))

В левой части примера rast находится поле географической матрицы и contains тип пространственного запроса. Справа geom геометрический вход и rst объект GDALRaster . Индекс бэнда по 0 умолчанию используется в первых двух запросах и установлен 1 в следующих.

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

Тип поддержки матрицы указан для каждого запроса в таблице совместимости . Запросы с матрицами в настоящее время доступны только для движка PostGIS.

Дистанционные запросы

Введение

Расчеты расстояния по пространственным данным сложны, потому что, к сожалению, Земля не плоская. Некоторые дистанционные запросы с полями в географической системе координат иногда нужно выражать по-другому из-за ограничений в PostGIS. Дополнительные сведения см. В разделе « Выбор SRID» в документации API модели GeoDjango .

Дистанционный поиск

Доступность  : PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (родной)

Доступны следующие варианты поиска на расстоянии:

Заметка

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

Поиск на расстоянии принимает параметр в виде кортежа, включая:

  1. Геометрический или матричный объект, на котором основываются вычисления; и
  2. Число или объект, Distance содержащий расстояние.

Если используется объект Distance , он может быть выражен в любых единицах (сгенерированный код SQL будет использовать единицы, преобразованные в единицы поля); в противном случае предполагается, что числовые параметры находятся в той же единице, что и поле.

Заметка

В PostGIS ST_Distance_Sphere больше не ограничиваются геометрические типы, к которым применяются запросы географического расстояния [3] . Однако эти запросы могут быть очень медленными, потому что расстояния большого круга должны вычисляться «на лету» для каждой строки в запросе. Причина в том, что пространственный индекс традиционных геометрических полей нельзя использовать.

Для повышения производительности дистанционных запросов WGS84 рассмотрите возможность использования столбцов географического типа в своей базе данных , поскольку их пространственный индекс можно использовать в дистанционных запросах. Вы можете указать GeoDjango создать географические столбцы, указав в определении geography=True поля.

Например, если у нас есть модель SouthTexasCity (пример взят из тестов расстояния GeoDjango ) с системой координат проекции, действующей для городов Южного Техаса:

from django.contrib.gis.db import models

class SouthTexasCity(models.Model):
    name = models.CharField(max_length=30)
    # A projected coordinate system (only valid for South Texas!)
    # is used, units are in meters.
    point = models.PointField(srid=32140)

Могут быть сделаны следующие дистанционные запросы:

>>> from django.contrib.gis.geos import GEOSGeometry
>>> from django.contrib.gis.measure import D # ``D`` is a shortcut for ``Distance``
>>> from geoapp.models import SouthTexasCity
# Distances will be calculated from this point, which does not have to be projected.
>>> pnt = GEOSGeometry('POINT(-96.876369 29.905320)', srid=4326)
# If numeric parameter, units of field (meters in this case) are assumed.
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, 7000))
# Find all Cities within 7 km, > 20 miles away, and > 100 chains away (an obscure unit)
>>> qs = SouthTexasCity.objects.filter(point__distance_lte=(pnt, D(km=7)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(mi=20)))
>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(pnt, D(chain=100)))

Матричные запросы работают таким же образом, заменяя геометрическое поле point боевым полем, или объект pnt матричным объектом, или тем и другим. Чтобы указать индекс полосы записи матрицы в правой части, троичный кортеж может быть передан в запрос следующим образом:

>>> qs = SouthTexasCity.objects.filter(point__distance_gte=(rst, 2, D(km=7)))

Где бэнд с индексом 2 (третий бэнд) матрицы rst будет использоваться для запроса.

Таблицы совместимости

Пространственные поиски

В следующей таблице представлена ​​сводка пространственных запросов, доступных для каждого механизма пространственной базы данных. PostGIS Raster (PGRaster) запросы делятся на три категории , описанные в Matrix Query Детали : Native N поддержка, Native двусторонней поддержки, B и поддержка преобразования Геометрическая C .

Тип исследования PostGIS оракул MariaDB MySQL [5] SpatiaLite PGRaster
bbcontains Икс   Икс Икс Икс НЕ
bboverlaps Икс   Икс Икс Икс НЕ
contained Икс   Икс Икс Икс НЕ
contains Икс Икс Икс Икс Икс В
contains_properly Икс         В
coveredby Икс Икс     Икс В
covers Икс Икс     Икс В
crosses Икс   Икс Икс Икс В.С.
disjoint Икс Икс Икс Икс Икс В
distance_gt Икс Икс Икс Икс Икс НЕ
distance_gte Икс Икс Икс Икс Икс НЕ
distance_lt Икс Икс Икс Икс Икс НЕ
distance_lte Икс Икс Икс Икс Икс НЕ
dwithin Икс Икс     Икс В
equals Икс Икс Икс Икс Икс В.С.
exact Икс Икс Икс Икс Икс В
intersects Икс Икс Икс Икс Икс В
isvalid Икс Икс   Х (≥ 5.7.5) X (LWGEOM)  
overlaps Икс Икс Икс Икс Икс В
relate Икс Икс Икс   Икс В.С.
same_as Икс Икс Икс Икс Икс В
touches Икс Икс Икс Икс Икс В
within Икс Икс Икс Икс Икс В
left Икс         В.С.
right Икс         В.С.
overlaps_left Икс         В
overlaps_right Икс         В
overlaps_above Икс         В.С.
overlaps_below Икс         В.С.
strictly_above Икс         В.С.
strictly_below Икс         В.С.

Функции базы данных

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

функция PostGIS оракул MariaDB MySQL SpatiaLite
Area Икс Икс Икс Икс Икс
AsGeoJSON Икс Икс Х (≥ 10.2.4) Х (≥ 5.7.5) Икс
AsGML Икс Икс     Икс
AsKML Икс       Икс
AsSVG Икс       Икс
AsWKB Икс Икс Икс Икс Икс
AsWKT Икс Икс Икс Икс Икс
Azimuth Икс       X (LWGEOM)
BoundingCircle Икс Икс      
Centroid Икс Икс Икс Икс Икс
Difference Икс Икс Икс Икс Икс
Distance Икс Икс Икс Икс Икс
Envelope Икс Икс Икс Икс Икс
ForcePolygonCW Икс       Икс
GeoHash Икс     Х (≥ 5.7.5) X (LWGEOM)
Intersection Икс Икс Икс Икс Икс
IsValid Икс Икс   Х (≥ 5.7.5) X (LWGEOM)
Length Икс Икс Икс Икс Икс
LineLocatePoint Икс       Икс
MakeValid Икс       X (LWGEOM)
MemSize Икс        
NumGeometries Икс Икс Икс Икс Икс
NumPoints Икс Икс Икс Икс Икс
Perimeter Икс Икс     Икс
PointOnSurface Икс Икс Икс   Икс
Reverse Икс Икс     Икс
Scale Икс       Икс
SnapToGrid Икс       Икс
SymDifference Икс Икс Икс Икс Икс
Transform Икс Икс     Икс
Translate Икс       Икс
Union Икс Икс Икс Икс Икс

Функции агрегирования

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

Метод агрегирования PostGIS оракул SpatiaLite
Collect Икс   Икс
Extent Икс Икс Икс
Extent3D Икс    
MakeLine Икс   Икс
Union Икс Икс Икс

Сноски

[1]См. Open Geospatial Consortium, Inc., OpenGIS Simple Feature Specification for SQL , Document 99-049 (5 мая 1999 г.), в главе 3.2.5, стр. 3-11 (Текстовое представление геометрии в SQL).
[2]См. PostGIS EWKB, EWKT и Canonical Forms , документацию PostGIS в гл. 4.1.2.
[3]Смотрите в документации PostGIS для ST_DistanceSphere .
[4]

См. Раздел Создание пространственных индексов в Справочном руководстве MySQL:

Для таблиц MyISAM создает индекс R-tree. Для механизмов хранения, которые поддерживают непространственные индексы для пространственных столбцов, механизм создает индекс B-дерева. Индекс B-дерева по пространственным значениям полезен для поиска точных значений, но не для интервального поиска.SPATIAL INDEX
[5]Обратитесь к разделу пространственных ограничений MySQL для получения более подробной информации.

Copyright ©2020 All rights reserved