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.

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

Истинные пространственные индексы (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 объектов обратитесь к руководству GEOS .

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

При создании растровых моделей растровое поле неявно преобразует входные данные в 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модель используется в GeoDjango Model API ):

>>> 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объект растровым объектом, или и то и другое. Чтобы указать индекс канала входного растра с правой стороны, 3-кортеж может быть передан поиску следующим образом:

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

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

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

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

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

Тип поиска PostGIS Oracle MariaDB MySQL [5] SpatiaLite PGRaster
bbcontains Икс   Икс Икс Икс N
bboverlaps Икс   Икс Икс Икс N
contained Икс   Икс Икс Икс N
contains Икс Икс Икс Икс Икс B
contains_properly Икс         B
coveredby Икс Икс     Икс B
covers Икс Икс     Икс B
crosses Икс   Икс Икс Икс C
disjoint Икс Икс Икс Икс Икс B
distance_gt Икс Икс Икс Икс Икс N
distance_gte Икс Икс Икс Икс Икс N
distance_lt Икс Икс Икс Икс Икс N
distance_lte Икс Икс Икс Икс Икс N
dwithin Икс Икс     Икс B
equals Икс Икс Икс Икс Икс C
exact Икс Икс Икс Икс Икс B
intersects Икс Икс Икс Икс Икс B
isvalid Икс Икс   Х (≥ 5.7.5) X (LWGEOM)  
overlaps Икс Икс Икс Икс Икс B
relate Икс Икс Икс   Икс C
same_as Икс Икс Икс Икс Икс B
touches Икс Икс Икс Икс Икс B
within Икс Икс Икс Икс Икс B
left Икс         C
right Икс         C
overlaps_left Икс         B
overlaps_right Икс         B
overlaps_above Икс         C
overlaps_below Икс         C
strictly_above Икс         C
strictly_below Икс         C

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

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

Функция PostGIS Oracle 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 Oracle 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 ©2021 All rights reserved