Spec-Zone.ru › Django 1.10

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 поддерживают только операции с прямоугольниками минимального охватывающего прямоугольника (MBR). В частности, MySQL не соответствует стандарту OGC:

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

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

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

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

Поддержка растров

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

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

RasterField теперь поддерживает пространственные запросы.

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

Вот пример того, как создать геометрический объект (предполагая модель 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] (требуется GDAL). По существу, если входной параметр не является объектом GEOSGeometry, поле геометрии попытается создать экземпляр GEOSGeometry из входных данных.

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

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

Новое в Django 1.9.

При создании растровых моделей растровое поле неявно преобразует входные данные в 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)}]},
... )

Пространственные запросы

Типы Lookups GeoDjango могут использоваться с любым методом менеджера, таким как filter(), exclude(), и т. д. Однако типы lookups, уникальные для 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.

Запросы к растровым данным

Новое в Django 1.10.

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

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

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

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

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

В следующей таблице представлен обзор доступных пространственных поисковых запросов для каждого пространственного бэкенда базы данных. Поисковые запросы для растровых данных PostGIS (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 B
equals X X X X C
exact X X X X B
intersects X X X X B
isvalid X
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
AsGML X X
AsKML X X
AsSVG X X
BoundingCircle 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 (≥ 4.0, LWGEOM)
Intersection X X X (≥ 5.6.1) X
IsValid X
Length X X X X
MakeValid X
MemSize X
NumGeometries X X X X
NumPoints X X X X
Perimeter X X X (≥ 4.0)
PointOnSurface X X X
Reverse X X X (≥ 4.0)
Scale X X
SnapToGrid X X (≥ 3.1)
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, The GeoJSON Format Specification, Ревизия 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/1.10/ref/contrib/gis/db-api/

Spec-Zone.ru

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