Spec-Zone.ru › Django 1.8

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 не поддерживают транзакции или ограничения внешних ключей.

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

Вот пример создания объекта геометрии (предполагается модель 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.

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

Типы запросов 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)

В этом случае, poly – это географическое поле, contains – тип пространственного запроса, а pnt – параметр (который может быть объектом GEOSGeometry или строкой GeoJSON, WKT или HEXEWKB).

Полная справка доступна в справке по пространственным запросам.

Примечание

GeoDjango строит пространственные запросы с помощью GeoQuerySet, подкласса QuerySet. Экземпляр GeoManager, прикреплённый к вашей модели, позволяет использовать GeoQuerySet.

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

Введение

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

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

Доступность: PostGIS, Oracle, SpatiaLite

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

  • distance_lt
  • distance_lte
  • distance_gt
  • distance_gte
  • dwithin

Примечание

Для измерения, а не запросов по расстоянию, используйте метод GeoQuerySet.distance().

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

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

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

Примечание

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

Для значительно лучшей производительности при запросах по расстоянию в системе WGS84, рассмотрите использование географических столбцов в вашей базе данных, так как они могут использовать свой пространственный индекс в запросах по расстоянию. Вы можете указать 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)
    objects = models.GeoManager()

Тогда запросы по расстоянию могут выполняться следующим образом:

>>> 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

GeoQuerySet Методы

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

Метод PostGIS Oracle SpatiaLite
GeoQuerySet.area() X X X
GeoQuerySet.centroid() X X X
GeoQuerySet.difference() X X X
GeoQuerySet.distance() X X X
GeoQuerySet.envelope() X X
GeoQuerySet.force_rhr() X
GeoQuerySet.geohash() X
GeoQuerySet.geojson() X X
GeoQuerySet.gml() X X X
GeoQuerySet.intersection() X X X
GeoQuerySet.kml() X X
GeoQuerySet.length() X X X
GeoQuerySet.mem_size() X
GeoQuerySet.num_geom() X X X
GeoQuerySet.num_points() X X X
GeoQuerySet.perimeter() X X
GeoQuerySet.point_on_surface() X X X
GeoQuerySet.reverse_geom() X X
GeoQuerySet.scale() X X
GeoQuerySet.snap_to_grid() X
GeoQuerySet.svg() X X
GeoQuerySet.sym_difference() X X X
GeoQuerySet.transform() X X X
GeoQuerySet.translate() X X
GeoQuerySet.union() X X X

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

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

Функция агрегации PostGIS Oracle SpatiaLite
Collect X (с версии 3.0)
Extent X X (с версии 3.0)
Extent3D X
MakeLine X
Union X X X

Примечания

[1] См. Консорциум по открытым геопространственным технологиям, Спецификация OpenGIS Simple Feature 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_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.8/ref/contrib/gis/db-api/

Spec-Zone.ru

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