GeoDjango База данных API
Пространственные бэкэнды
GeoDjango в настоящее время предоставляет следующие пространственные бэкэнды базы данных:
django.contrib.gis.db.backends.postgisdjango.contrib.gis.db.backends.mysqldjango.contrib.gis.db.backends.oracledjango.contrib.gis.db.backends.spatialite
Ограничения MySQL для пространственных данных
Пространственные расширения 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 (Хорошо известный текст [1]), HEXEWKB (специфичный для PostGIS – геометрия WKB в шестнадцатеричном формате [2]) и GeoJSON [3] (требует GDAL). По существу, если входной параметр не является объектом 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)
В этом случае, poly – это географическое поле, contains – это тип пространственного запроса, а pnt – это параметр (который может быть объектом GEOSGeometry или строкой GeoJSON, WKT или HEXEWKB).
Полная справка находится в справочнике по пространственным запросам.
Запросы по расстоянию
Введение
Вычисление расстояний с пространственными данными сложно, потому что Земля не плоская. Некоторые запросы по расстоянию с полями в географической системе координат могут потребовать другого выражения из-за ограничений PostGIS. Подробности см. в разделе Выбор SRID документации GeoDjango Модельный API.
Запросы по расстоянию
Доступно: PostGIS, Oracle, SpatiaLite
Доступны следующие запросы по расстоянию:
Примечание
Для измерения, а не для запроса по расстояниям, используйте функцию Distance.
Запросы по расстоянию принимают кортеж параметров, содержащий:
- Геометрию для расчёта расстояния; и
- Число или объект
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)))
Таблицы совместимости
Пространственные запросы
В следующей таблице содержится сводка доступных пространственных запросов для каждого пространственного бэкэнда базы данных.
| Тип поиска | PostGIS | Oracle | MySQL [6] | SpatiaLite |
|---|---|---|---|---|
bbcontains | X | X | X | |
bboverlaps | X | X | X | |
contained | X | X | X | |
contains | X | X | X | X |
contains_properly | X | |||
coveredby | X | X | ||
covers | X | X | ||
crosses | X | X | ||
disjoint | X | X | X | X |
distance_gt | X | X | X | |
distance_gte | X | X | X | |
distance_lt | X | X | X | |
distance_lte | X | X | X | |
dwithin | X | X | ||
equals | X | X | X | X |
exact | X | X | X | X |
intersects | X | X | X | X |
overlaps | X | X | X | X |
relate | X | X | X | |
same_as | X | X | X | X |
touches | X | X | X | X |
within | X | X | X | X |
left | X | |||
right | X | |||
overlaps_left | X | |||
overlaps_right | X | |||
overlaps_above | X | |||
overlaps_below | X | |||
strictly_above | X | |||
strictly_below | X |
Функции баз данных
В следующей таблице приведены сведения о доступных геоспецифичных функциях баз данных для каждого пространственного бэкенда.
| Функция | 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 | |
Distance | X | X | X (≥ 5.6.1) | X |
Envelope | X | X | X | |
ForceRHR | X | |||
GeoHash | X | |||
Intersection | X | X | X | |
Length | X | X | X | 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 | |
Transform | X | X | X | |
Translate | X | X | ||
Union | X | X | X (≥ 5.6.1) | X |
Функции агрегирования
В следующей таблице представлен обзор доступных функций агрегирования для пространственных баз данных на каждом пространственном бэкенде. Обратите внимание, что MySQL не поддерживает ни одну из этих функций агрегирования и, следовательно, исключен из таблицы.
| Функция агрегирования | PostGIS | Oracle | SpatiaLite |
|---|---|---|---|
Collect | X | (с версии 3.0) | |
Extent | X | X | (с версии 3.0) |
Extent3D | X | ||
MakeLine | 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_distance_sphere. |
| [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.9/ref/contrib/gis/db-api/