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

Django supports spatial functions operating on real geometries available in modern MySQL versions. However, the spatial functions are not as rich as other backends like PostGIS.

Поддержка растровых изображений

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 (Well Known Text [1]), HEXEWKB (специфика PostGIS - геометрия WKB в шестнадцатеричном формате [2]) и GeoJSON (см. RFC 7946). По существу, если входные данные не являются объектом GEOSGeometry, поле геометрии попытается создать экземпляр GEOSGeometry из входных данных.

Подробнее о создании объектов GEOSGeometry см. в разделе GEOS tutorial.

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

При создании растровых моделей поле raster будет неявно преобразовывать входные данные в 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) могут быть объединены с фильтрами на географических полях. Географический поиск принимает геометрические и растровые данные с обеих сторон, и типы данных можно смешивать.

Ниже описана общая структура географических поисков. Полный справочник можно найти в разделе spatial lookup reference.

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

Географические запросы с геометрией имеют следующий общий вид (предполагая модель 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 в остальных.

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

Тип поддержки растров указан для всех поисков в compatibility table. В настоящее время поиск с использованием растров доступен только для бэкенда PostGIS.

Запросы о расстоянии

Вступление

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

Поиск расстояний

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

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

Примечание

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

Для поиска расстояния используется кортеж параметров, состоящий из:

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

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

Примечание

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

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

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

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) делятся на три категории, описанные в raster lookup details: «родная» поддержка N, двусторонняя «родная» поддержка B и поддержка преобразования геометрии C.

Тип поиска ПостГИС Oracle MariaDB MySQL [4] SpatiaLite PGRaster
bbcontains X   X X X N
bboverlaps X   X X X N
contained X   X X X N
contains X X X X X B
contains_properly X         B
coveredby X X     X B
covers X X     X B
crosses X   X X X C
disjoint X X X X X B
distance_gt X X X X X N
distance_gte X X X X X N
distance_lt X X X X X N
distance_lte X X X X X N
dwithin X X     X B
equals X X X X X C
exact X X X X X B
intersects X X X X X B
isvalid X X   X X  
overlaps X X X X X B
relate X X X   X C
same_as X X X X X B
touches X X X X X B
within X X X X X B
left X         C
right X         C
overlaps_left X         B
overlaps_right X         B
overlaps_above X         C
overlaps_below X         C
strictly_above X         C
strictly_below X         C

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

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

Функция ПостГИС Oracle MariaDB MySQL SpatiaLite
Area X X X X X
AsGeoJSON X X X X X
AsGML X X     X
AsKML X       X
AsSVG X       X
AsWKB X X X X X
AsWKT X X X X X
Azimuth X       X (LWGEOM/RTTOPO)
BoundingCircle X X      
Centroid X X X X X
Difference X X X X X
Distance X X X X X
Envelope X X X X X
ForcePolygonCW X       X
GeoHash X     X X (LWGEOM/RTTOPO)
Intersection X X X X X
IsValid X X   X X
Length X X X X X
LineLocatePoint X       X
MakeValid X       X (LWGEOM/RTTOPO)
MemSize X        
NumGeometries X X X X X
NumPoints X X X X X
Perimeter X X     X
PointOnSurface X X X   X
Reverse X X     X
Scale X       X
SnapToGrid X       X
SymDifference X X X X X
Transform X X     X
Translate X       X
Union X X X X X

Агрегатные функции

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

A ПостГИС Oracle SpatiaLite
Collect X   X
Extent X X X
Extent3D X    
MakeLine X   X
Union X X X

Сноски

[1]See Open Geospatial Consortium, Inc., OpenGIS Simple Feature Specification For SQL, Document 99-049 (May 5, 1999), at Ch. 3.2.5, p. 3-11 (SQL Textual Representation of Geometry).
[2]**Смотрите* PostGIS EWKB, EWKT и канонические формы, документация PostGIS в гл. 4.1.2.
[3]Смотрите Документацию PostGIS <https://postgis.net/docs/ST_DistanceSphere.html>`_ по ``ST_DistanceSphere.
[4]Более подробную информацию смотрите в разделе Пространственные ограничения MySQL.
Вернуться на верх