GeoDjango Database API

Spatial Backends

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 Limitations

MySQL的空间扩展只支持边界框操作(什么MySQL调用最小边界矩形,或MBR)。 具体来说,MySQL不符合OGC标准

Currently, MySQL does not implement these functions [Contains, Crosses, Disjoint, Intersects, Overlaps, Touches, Within] according to the specification. 那些被实现的返回与相应的基于MBR的功能相同的结果。

换句话说,虽然在使用MySQL时,在GeoDjango中可以使用contains的空间查找,但返回的结果实际上等效于在不同的空间上使用bbcontains后端。

警告

只有MySQL上的MyISAM表支持真空间索引(R-树)。 [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 specific - 十六进制中的WKB几何)传递几何参数[2])和GeoJSON [3] 实质上,如果输入不是GEOSGeometry对象,则几何字段将尝试从输入创建GEOSGeometry实例。

有关创建GEOSGeometry对象的更多信息,请参阅GEOS tutorial

使用光栅字段创建和保存模型

创建栅格模型时,栅格字段将使用延迟评估将输入隐式转换为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)}]},
... )

Spatial Lookups

GeoDjango的查找类型可以用于任何管理器方法,例如filter()exclude()等。 但是,GeoDjango唯一的查找类型仅适用于空间字段。

“正常”字段上的过滤器(例如CharField)可能与地理字段上的过滤器链接。 地理查询接受两边的几何和栅格输入,输入类型可以自由混合。

地理查询的一般结构如下所述。 完整的引用可以在spatial lookup reference中找到。

几何查找

具有几何的地理查询使用以下通用格式(假设在GeoDjango Model API中使用的Zipcode模型):

>>> 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)。 在这种情况下,语法与几何查找的语法相同。

要指定频带索引,可以在查找的两边指定一个附加参数。 在左侧,双下划线语法用于传递带索引。 在右侧,可以指定光栅和带索引的元组。

这导致了关于栅格的查找的以下通用形式(假设在GeoDjango Model API中使用的Elevation模型):

>>> 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是空间查找类型。 On the right hand side, geom is a geometry input and rst is a GDALRaster object. 在前两个查询中,频带索引默认为0,其他索引被设置为1

虽然所有空间查找都可以与两边的栅格对象一起使用,但并非所有底层操作符本身都接受栅格输入。 对于运算符期望几何输入的情况,栅格将自动转换为几何。 在解释查找结果时要牢记这一点。

列出了compatibility table中所有查找的栅格支持类型。 涉及栅格的查找目前仅适用于PostGIS后端。

Distance Queries

Introduction

使用空间数据的距离计算很棘手,因为不幸的是,地球不平。 由于PostGIS中的限制,具有地理坐标系中的字段的一些距离查询可能必须被不同地表示。 有关详情,请参阅GeoDjango Model API文档中的Selecting an SRID部分。

Distance Lookups

可用性:PostGIS,Oracle,SpatiaLite,PGRaster(Native)

以下距离查找可用:

对于测量,而不是在距离上查询,请使用Distance功能。

距离查找采用元组参数,包括:

  1. 几何或栅格到基础计算;和
  2. 包含距离的数字或Distance对象。

如果使用Distance对象,它可以以任何单位表示(生成的SQL将使用转换为字段的单位的单位);否则,假设数字参数以字段为单位。

在PostGIS中,ST_Distance_Sphere 限制使用地理距离查询执行的几何类型。 [4]但是,这些查询可能需要很长时间,因为必须为查询中的行动态计算大圆距离。 这是因为传统几何字段上的空间索引不能使用。

要在WGS84距离查询上获得更好的性能,请考虑在数据库中使用geography columns,因为它们能够在距离查询中使用其空间索引。 您可以通过在字段定义中设置geography=True来让GeoDjango使用地理位置列。

例如,假设我们在有效于得克萨斯州南部城市的投影坐标系统上有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)))

栅格查询的工作方式相同,只需用栅格对象或两者即可将栅格字段或pnt对象替换为几何域point 要指定右侧光栅输入的波段索引,可以按如下方式将3元组传递给查找:

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

其中光栅rst的索引2(第三个带)的频带将用于查找。

Compatibility Tables

Spatial Lookups

下表提供了每个空间数据库后端可用的空间查找的摘要。 PostGIS光栅(PGRaster)查找被分为在raster lookup details中描述的三个类别:本机支持N,双边本机支持B和几何转换支持C

查找类型 PostGIS Oracle MySQL [6] SpatiaLite PGRaster
bbcontains X   X X N
bboverlaps X   X X N
X   X X N
contains X X X X B
contains_properly X       B
覆盖 X X     B
盖子 X X     B
十字架 X     X C
不相交的 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
等于 X X X X C
exact X X X X B
相交 X X X X B
已验证 X X   X(LWGEOM)  
重叠 X X X X B
涉及 X X   X C
与...一样 X X X X B
触摸 X X X X B
X X X X B
剩下 X       C
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
X X X X
AsGeoJSON X     X
AsGML X X   X
AsKML X     X
AsSVG X     X
BoundingCircle X X(≥12.1.0.2)    
形心 X X X X
区别 X X X(≥5.6.1) X
距离 X X X(≥5.6.1) X
信封 X   X X
ForceRHR X      
地理散列 X     X(LWGEOM)
路口 X X X(≥5.6.1) X
已验证 X X   X(LWGEOM)
长度 X X X X
MakeValid X     X(LWGEOM)
MEMSIZE X      
NumGeometries X X X X
为NumPoints X X X X
周长 X X   X
PointOnSurface X X   X
相反 X X   X
规模 X     X
SnapToGrid X     X
SymDifference X X X(≥5.6.1) X
转变 X X   X
翻译 X     X
联盟 X X X(≥5.6.1) X

Aggregate Functions

下表提供了每个空间后端可用的特定于GIS的聚合函数的摘要。 请注意,MySQL不支持任何这些聚合,因此从表中排除。

骨料 PostGIS Oracle SpatiaLite
搜集 X   X
程度 X X X
Extent3D X    
MakeLine X   X
联盟 X X X

脚注

[1]请参阅 Open Geospatial Consortium,Inc.,OpenGIS Simple Feature Specification For SQL,Document 99-049(1999年5月5日) 3.2.5,p。 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(2008年6月16日)。
[4]请参见ST_DistanceSphere上的 PostGIS文档
[5]

请参阅MySQL参考手册中的 创建空间索引

对于MyISAM表,SPATIAL INDEX创建一个R树索引。 对于支持空间列非空间索引的存储引擎,引擎创建一个B树索引。 空间值上的B树索引对精确值查找有用,但不适用于范围扫描。
[6]有关详细信息,请参阅MySQL Spatial Limitations部分。