Spec-Zone.ru › Django 2.0

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

Пространственные бэкенды

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 Spatial

Пространственные расширения MySQL поддерживают только операции с ограничивающей прямоугольной областью (которые MySQL называет минимальными ограничивающими прямоугольниками, или MBR). В частности, MySQL не соответствует стандарту OGC:

В настоящее время MySQL не реализует эти функции [Contains, Crosses, Disjoint, Intersects, Overlaps, Touches, Within] в соответствии со спецификацией. Реализованные функции возвращают тот же результат, что и соответствующие функции, основанные на MBR.

Другими словами, хотя пространственные запросы, такие как contains доступны в GeoDjango при использовании MySQL, возвращаемые результаты фактически эквивалентны результатам, которые были бы возвращены при использовании bbcontains в другом пространственном бэкенде.

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

Истинные пространственные индексы (R-деревья) поддерживаются только с таблицами MyISAM в MySQL. [5] Другими словами, при использовании пространственных расширений 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 (Well Known Text [1]), HEXEWKB (PostGIS-специфический – геометрия WKB в шестнадцатеричном формате [2]) и GeoJSON [3]. В сущности, если вход не является объектом 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 Модель 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 используемой в GeoDjango Модель API):

>>> 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 в документации GeoDjango Модель API.

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

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

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

  • distance_lt
  • distance_lte
  • distance_gt
  • distance_gte
  • dwithin

Примечание

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

Запросы расстояния принимают кортеж параметров, состоящий из:

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

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

Примечание

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

Для значительно лучшей производительности при запросах расстояния в 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 MySQL [6] SpatiaLite PGRaster
bbcontains X X X N
bboverlaps X X X N
contained X X X N
contains X X X X B
contains_properly X B
coveredby X X B
covers X X B
crosses X X C
disjoint X X X X B
distance_gt X X X N
distance_gte X X X N
distance_lt X X X N
distance_lte X X X N
dwithin X X X B
equals X X X X C
exact X X X X B
intersects X X X X B
isvalid X X X (≥ 5.7.5) X (LWGEOM)
overlaps X X X X B
relate X X X C
same_as X X X X B
touches X X X X B
within 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

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

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

Функция PostGIS Oracle MySQL SpatiaLite
Area X X X X
AsGeoJSON X X (≥ 5.7.5) X
AsGML X X X
AsKML X X
AsSVG X X
Azimuth X X (LWGEOM)
BoundingCircle X X
Centroid X X X X
Difference X X X (≥ 5.6.1) X
Distance X X X (≥ 5.6.1) X
Envelope X X X
ForceRHR X
GeoHash X X (≥ 5.7.5) X (LWGEOM)
Intersection X X X (≥ 5.6.1) X
IsValid X X X (≥ 5.7.5) X (LWGEOM)
Length X X X X
LineLocatePoint X X
MakeValid X X (LWGEOM)
MemSize X
NumGeometries X X X X
NumPoints X X X X
Perimeter X X X
PointOnSurface X X X
Reverse X X X
Scale X X
SnapToGrid X X
SymDifference X X X (≥ 5.6.1) X
Transform X X X
Translate X X
Union X X X (≥ 5.6.1) X

Функции агрегации

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

Агрегат PostGIS Oracle SpatiaLite
Collect X X
Extent X X X
Extent3D X
MakeLine X X
Union X X X

Примечания

[1] См. Open Geospatial Consortium, Inc., OpenGIS Simple Feature Specification For SQL, Документ 99-049 (5 мая 1999 г.), в разделе 3.2.5, стр. 3-11 (текстовое представление геометрии SQL).
[2] См. PostGIS EWKB, EWKT и канонические формы, документацию PostGIS в разделе 4.1.2.
[3] См. Howard Butler, Martin Daly, Allan Doyle, Tim Schaub, & Christopher Schmidt, Спецификацию формата GeoJSON, Пересмотр 1.0 (16 июня 2008 г.).
[4] См. документацию PostGIS по ST_DistanceSphere.
[5]

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

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

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.0/ref/contrib/gis/db-api/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API