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(Well Known Text [1])、HEXEWKB(PostGIS 特定的十六进制 WKB 几何图形[#fnewkb]_)和 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 的查找类型仅在空间字段上可用。
对于 ‘normal’ 字段(例如 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 的限制,一些在地理坐标系统中的距离查询可能必须以不同的方式表示。有关更多详细信息,请参阅 GeoDjango 模型 API 文档中的 选择一个 SRID 部分。
距离查找
可用性 :PostGIS, MariaDB, MySQL, Oracle, SpatiaLite, PGRaster (Native)
以下是可用的距离查找:
- distance_lt
- distance_lte
- distance_gt
- distance_gte
- dwithin (除了 MariaDB 和 MySQL)
备注
对于 测量,而不是查询距离,使用 Distance
函数。
距离查找需要一个元组参数,包括:
- 用于计算的几何体或栅格;和
- 一个数字或 Distance 对象,包含距离。
如果使用了 Distance 对象,它可以用任何单位表示(生成的 SQL 将使用转换为字段单位的单位);否则,数字参数被认为是字段的单位。
备注
在 PostGIS 中,ST_Distance_Sphere
不限制地理距离查询所使用的几何类型。然而,这些查询可能会花费很长时间,因为必须为查询中的每一行动态计算大圆距离。这是因为传统几何字段上的空间索引无法使用。
为了在 WGS84 距离查询中获得更好的性能,考虑在数据库中使用 地理列,因为它们能够在距离查询中使用它们的空间索引。您可以通过在字段定义中设置 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)))
栅格查询的工作方式相同,只需将几何字段 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 |
relate | X | X | X | X | C | |
same_as | X | X | X | X | X | B |
touches | X | X | X | X | X | B |
within | X | 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 | MariaDB | MySQL | SpatiaLite |
---|---|---|---|---|---|
Area | 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 |
Azimuth | X | X (LWGEOM/RTTOPO) | |||
BoundingCircle | X | X | |||
Centroid | X | X | X | X | X |
Difference | X | X | X | X | X |
Distance | X | X | X | X | X |
Envelope | 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) | ||
Intersection | X | X | X | X | X |
IsEmpty | X | ||||
IsValid | X | X | X | X | |
Length | 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 |
Perimeter | 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 | |||
Union | X | X | X | X | X |
聚合函数
以下表格提供了每个空间后端可用的 GIS 专用聚合函数的摘要。请注意,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(1999 年 5 月 5 日),第 3.2.5 章,第 3-11 页(几何图形的 SQL 文本表示)。 |
[2] | 请参阅 PostGIS EWKB、EWKT 和规范形式,PostGIS 文档第 4.1.2 章。 |
[3] | 请参阅 PostGIS 文档 中关于 ST_DistanceSphere 的部分。 |
[4] | 详情请参考 MySQL 的空间限制 部分。 |