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 空间限制¶
Django 支持在现代 MySQL 版本中可用的真实几何图形上的空间函数。但是,空间函数不如 PostGIS 等其他后端丰富。
栅格支持¶
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(请参阅 RFC 7946)传递几何参数。从本质上讲,如果输入不是 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
)的过滤器可以与地理字段上的过滤器链接。地理查找在两侧都接受几何和栅格输入,并且可以自由混合输入类型。
地理查找的一般结构如下所述。可以在 空间查找参考 中找到完整参考。
几何查找¶
使用几何的地理查询采用以下通用形式(假设 GeoDjango 模型 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
对象。
栅格查找¶
栅格查找语法类似于几何的语法。唯一的区别是,可以将波段索引指定为附加输入。如果未指定波段索引,则默认使用第一个波段(索引 0
)。在这种情况下,语法与几何查找的语法相同。
要指定波段索引,可以在查找的两侧指定附加参数。在左侧,双下划线语法用于传递波段索引。在右侧,可以指定栅格和波段索引的元组。
这导致涉及栅格的查找具有以下通用形式(假设在 GeoDjango 模型 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
是空间查找类型。在右侧,geom
是几何输入,rst
是 GDALRaster
对象。在最初两个查询中,波段索引默认为 0
,在其他查询中设置为 1
。
虽然所有空间查找都可以与两侧的栅格对象一起使用,但并非所有底层运算符都原生接受栅格输入。对于运算符期望几何输入的情况,栅格会自动转换为几何。在解释查找结果时,记住这一点很重要。
所有查找的栅格支持类型在 兼容性表 中列出。涉及栅格的查找目前仅适用于 PostGIS 后端。
距离查询¶
简介¶
使用空间数据进行距离计算很棘手,因为不幸的是,地球不是平的。由于 PostGIS 中的限制,某些地理坐标系中的字段的距离查询可能必须以不同的方式表示。有关更多详细信息,请参阅 选择 SRID 部分中的 GeoDjango 模型 API 文档。
距离查找¶
可用性:PostGIS、MariaDB、MySQL、Oracle、SpatiaLite、PGRaster(本机)
以下距离查找可用
distance_lt
distance_lte
distance_gt
distance_gte
dwithin
(MariaDB 和 MySQL 除外)
注意
对于测量,而不是查询距离,请使用 Distance
函数。
距离查找采用包含以下内容的元组参数
- 用于计算的几何或栅格;以及
- 包含距离的数字或
Distance
对象。
如果使用 Distance
对象,则可以使用任何单位表示(生成的 SQL 将使用转换为字段单位的单位);否则,假定数字参数以字段单位表示。
注意
在 PostGIS 中,ST_Distance_Sphere
不会限制执行地理距离查询的几何类型。[3] 但是,这些查询可能需要很长时间,因为必须为查询中的每一行动态计算大圆距离。这是因为无法使用传统几何字段上的空间索引。
为了在 WGS84 距离查询中获得更好的性能,请考虑在数据库中使用 geography 列,因为它们可以在距离查询中使用其空间索引。您可以通过在字段定义中设置 geography=True
来告知 GeoDjango 使用 geography 列。
例如,假设我们有一个 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)))
其中栅格 rst
的索引为 2(第三个波段)的波段将用于查找。
兼容性表¶
空间查找¶
下表总结了每个空间数据库后端可用的空间查找。PostGIS 栅格 (PGRaster) 查找分为 栅格查找详细信息 中描述的三类:本机支持 N
、双边本机支持 B
和几何转换支持 C
。
查找类型 | PostGIS | Oracle | MariaDB | MySQL [4] | SpatiaLite | PGRaster |
---|---|---|---|---|---|---|
bbcontains |
X | X | X | X | N | |
bboverlaps |
X | X | X | X | N | |
contained |
X | X | X | X | N | |
contains |
X | X | X | X | X | B |
contains_properly |
X | B | ||||
coveredby |
X | X | X | B | ||
covers |
X | X | X | B | ||
crosses |
X | X | X | X | C | |
disjoint |
X | X | X | X | X | B |
distance_gt |
X | X | X | X | X | N |
distance_gte |
X | X | X | X | X | N |
distance_lt |
X | X | X | X | X | N |
distance_lte |
X | X | X | X | X | N |
dwithin |
X | X | X | B | ||
equals |
X | X | X | X | X | C |
exact |
X | X | X | X | X | B |
intersects |
X | X | X | X | X | B |
isempty |
X | |||||
isvalid |
X | X | X | X | ||
overlaps |
X | X | X | X | X | B |
关联 |
X | X | X | X | C | |
相同 |
X | X | X | X | X | B |
接触 |
X | X | X | X | X | B |
在内部 |
X | X | X | X | X | B |
左侧 |
X | C | ||||
右侧 |
X | C | ||||
左重叠 |
X | B | ||||
右重叠 |
X | B | ||||
上重叠 |
X | C | ||||
下重叠 |
X | C | ||||
严格在上 |
X | C | ||||
严格在下 |
X | C |
数据库函数¶
下表总结了每个空间后端上可用的地理特定数据库函数。
函数 | PostGIS | Oracle | MariaDB | MySQL | SpatiaLite |
---|---|---|---|---|---|
面积 |
X | X | X | X | X |
AsGeoJSON |
X | X | X | X | X |
AsGML |
X | X | X | ||
AsKML |
X | X | |||
AsSVG |
X | X | |||
AsWKB |
X | X | X | X | X |
AsWKT |
X | X | X | X | X |
方位角 |
X | X (LWGEOM/RTTOPO) | |||
边界圆 |
X | X | |||
质心 |
X | X | X | X | X |
最近点 |
X | X | |||
差 |
X | X | X | X | X |
距离 |
X | X | X | X | X |
包络 |
X | X | X | X | X |
ForcePolygonCW |
X | X | |||
FromWKB |
X | X | X | X | X |
FromWKT |
X | X | X | X | X |
GeoHash |
X | X | X (LWGEOM/RTTOPO) | ||
交集 |
X | X | X | X | X |
IsEmpty |
X | ||||
IsValid |
X | X | X | X | |
长度 |
X | X | X | X | X |
LineLocatePoint |
X | X | |||
MakeValid |
X | X (LWGEOM/RTTOPO) | |||
MemSize |
X | ||||
NumGeometries |
X | X | X | X | X |
NumPoints |
X | X | X | X | X |
周长 |
X | X | X | ||
PointOnSurface |
X | X | X | X | |
Reverse |
X | X | X | ||
Scale |
X | X | |||
SnapToGrid |
X | X | |||
SymDifference |
X | X | X | X | X |
Transform |
X | X | X | ||
Translate |
X | X | |||
并集 |
X | X | X | X | X |
聚合函数¶
下表总结了每个空间后端上可用的 GIS 特定聚合函数。请注意,MySQL 不支持任何这些聚合,因此从表中排除。
聚合 | PostGIS | Oracle | SpatiaLite |
---|---|---|---|
收集 |
X | X | |
范围 |
X | X | X |
范围 3D |
X | ||
MakeLine |
X | X | |
并集 |
X | X | X |
脚注
[1] | 参见开放地理空间联盟公司,SQL 的 OpenGIS 简单要素规范,文档 99-049(1999 年 5 月 5 日),第 3.2.5 章,第 3-11 页(几何的 SQL 文本表示)。 |
[2] | 参见 PostGIS EWKB、EWKT 和规范形式,PostGIS 文档第 4.1.2 章。 |
[3] | 参见 PostGIS 文档上的 ST_DistanceSphere 。 |
[4] | 有关更多详细信息,请参阅 MySQL 空间限制 部分。 |