GeoDjango 数据库 API — Django 文档
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 空间限制
在 MySQL 5.6.1 之前,空间扩展只支持边界框操作(MySQL 称之为最小边界矩形,或 MBR)。 具体来说,MySQL 不符合 OGC 标准。 Django 支持在现代 MySQL 版本中可用的真实几何图形上运行的空间函数。 但是,空间功能不如其他后端如 PostGIS 丰富。
警告
只有 MySQL 上的 MyISAM 表才支持真正的空间索引 (R-tree)。 4 换句话说,当使用 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 特定 – 十六进制 2 中的 WKB 几何)传递几何参数和 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
是地理场, :lookup:`包含 ` 是空间查找类型,pnt
是参数(可能是一个几何图形对象或一串 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
是地理栅格字段和 :lookup:`包含 ` 是空间查找类型。 在右侧,geom
是几何输入,rst
是 GDALRaster 对象。 波段索引在前两个查询中默认为 0
,在其他查询中设置为 1
。
虽然所有空间查找都可以用于两侧的栅格对象,但并非所有底层运算符都本机接受栅格输入。 对于操作员需要几何输入的情况,栅格会自动转换为几何。 在解释查找结果时记住这一点很重要。
在 兼容性表 中列出了所有查找的栅格支持类型。 涉及栅格的查找目前仅适用于 PostGIS 后端。
距离查询
简介
使用空间数据计算距离很棘手,因为不幸的是,地球不是平的。 由于 PostGIS 的限制,某些地理坐标系中字段的距离查询可能必须以不同的方式表达。 有关更多详细信息,请参阅 GeoDjango 模型 API 文档中的 选择 SRID 部分。
距离查找
可用性:PostGIS、MariaDB、MySQL、Oracle、SpatiaLite、PGRaster(原生)
以下距离查找可用:
- :lookup:`distance_lt`
- :lookup:`distance_lte`
- :lookup:`distance_gt`
- :lookup:`distance_gte`
- :lookup:`dwithin`(MariaDB 和 MySQL 除外)
距离查找采用元组参数,包括:
- 作为基础计算的几何或栅格; 和
- 包含距离的数字或 Distance 对象。
如果使用 Distance 对象,则可以用任意单位表示(生成的 SQL 将使用转换为字段的单位); 否则,假定数字参数以字段为单位。
笔记
在 PostGIS 中,ST_Distance_Sphere
并 not 限制执行地理距离查询的几何类型。 3 但是,这些查询可能需要很长时间,因为必须为查询中的 每 行动态计算大圆距离。 这是因为无法使用传统几何字段上的空间索引。
为了在 WGS84 距离查询上获得更好的性能,请考虑在数据库中使用 地理列 ,因为它们能够在距离查询中使用其空间索引。 您可以通过在字段定义中设置 geography=True
来告诉 GeoDjango 使用地理列。
例如,假设我们有一个SouthTexasCity
模型(来自 :source:`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
和几何转换支持 [ X219X]。
查找类型 | 地理信息系统 | 甲骨文 | 玛丽亚数据库 | MySQL 5 | SpatiaLite | 程序员 |
---|---|---|---|---|---|---|
:lookup:`bbcontains` | X | X | X | X | N | |
:lookup:`bboverlaps` | X | X | X | X | N | |
:查找:`包含` | X | X | X | X | N | |
:lookup:`包含 ` | X | X | X | X | X | B |
:lookup:`contains_properly` | X | B | ||||
:lookup:`coveredby` | X | X | X | B | ||
:查找:`封面` | X | X | X | B | ||
:查找:`十字架` | X | X | X | X | C | |
:查找:`不相交` | X | X | X | X | X | B |
:lookup:`distance_gt` | X | X | X | X | X | N |
:lookup:`distance_gte` | X | X | X | X | X | N |
:lookup:`distance_lt` | X | X | X | X | X | N |
:lookup:`distance_lte` | X | X | X | X | X | N |
:lookup:`dwithin` | X | X | X | B | ||
:查找:`等于` | X | X | X | X | X | C |
:lookup:`确切 ` | X | X | X | X | X | B |
:lookup:`相交` | X | X | X | X | X | B |
:lookup:`无效` | X | X | X (≥ 5.7.5) | X (LWGEOM) | ||
:lookup:`重叠` | X | X | X | X | X | B |
:查找:`相关` | X | X | X | X | C | |
:lookup:`same_as` | X | X | X | X | X | B |
:查找:`触摸` | X | X | X | X | X | B |
:lookup:`内` | X | X | X | X | X | B |
:查找:`左` | X | C | ||||
:查找:`正确` | X | C | ||||
:lookup:`overlaps_left` | X | B | ||||
:lookup:`overlaps_right` | X | B | ||||
:lookup:`overlaps_above` | X | C | ||||
:lookup:`overlaps_below` | X | C | ||||
:lookup:`严格在上面` | X | C | ||||
:lookup:`严格在下面` | X | C |
数据库功能
下表提供了每个空间后端可用的特定于地理的数据库功能的摘要。
功能 | 地理信息系统 | 甲骨文 | 玛丽亚数据库 | MySQL | SpatiaLite |
---|---|---|---|---|---|
Area
|
X | X | X | X | X |
AsGeoJSON
|
X | X | X (≥ 10.2.4) | X (≥ 5.7.5) | 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) | |||
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 | |||
GeoHash
|
X | X (≥ 5.7.5) | X (LWGEOM) | ||
Intersection
|
X | X | X | X | X |
IsValid
|
X | X | X (≥ 5.7.5) | X (LWGEOM) | |
Length
|
X | X | X | X | X |
LineLocatePoint
|
X | X | |||
MakeValid
|
X | X (LWGEOM) | |||
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 不支持任何这些聚合,因此从表中排除。
聚合 | 地理信息系统 | 甲骨文 | 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 日),在 Ch。 3.2.5,第。 3-11(几何的 SQL 文本表示)。
- 2
看 PostGIS EWKB、EWKT 和规范形式, PostGIS documentation at Ch. 4.1.2.
- 3
看 PostGIS 文档 on
ST_DistanceSphere
.- 4
看 创建空间索引 in the MySQL Reference Manual:
对于 MyISAM 表,
SPATIAL INDEX
创建 R 树索引。 对于支持空间列的非空间索引的存储引擎,引擎会创建 B 树索引。 空间值上的 B 树索引将用于精确值查找,但不适用于范围扫描。- 5
有关更多详细信息,请参阅 MySQL 空间限制 部分。