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のような他のバックエンドほど豊富ではありません。
警告
真の空間インデックス(Rツリー)は、MySQLのMyISAMテーブルでのみサポートされます。 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(Well Know Text 1 )、HEXEWKB(PostGIS固有–16進数の 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
パラメータです(これは 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
は地理ラスターフィールドであり、 :lookup: `含む ` 空間ルックアップタイプです。 右側では、geom
はジオメトリ入力であり、rst
は GDALRaster オブジェクトです。 バンドインデックスは、最初の2つのクエリではデフォルトで0
に設定され、その他のクエリでは1
に設定されます。
すべての空間ルックアップは両側のラスターオブジェクトで使用できますが、基礎となるすべての演算子がラスター入力をネイティブに受け入れるわけではありません。 オペレーターがジオメトリ入力を期待している場合、ラスターは自動的にジオメトリに変換されます。 ルックアップ結果を解釈するときは、これを覚えておくことが重要です。
ラスターサポートのタイプは、互換性テーブルのすべてのルックアップにリストされています。 ラスターを含むルックアップは現在、PostGISバックエンドでのみ利用可能です。
距離クエリ
序章
残念ながら、地球は平坦ではないため、空間データを使用した距離計算には注意が必要です。 PostGISの制限により、地理座標系のフィールドを使用した一部の距離クエリは、異なる方法で表現する必要がある場合があります。 詳細については、 GeoDjango Model 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
は地理的距離クエリが実行されるジオメトリタイプを制限しません。 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のバンド(3番目のバンド)がルックアップに使用される場合。
互換性テーブル
空間ルックアップ
次の表に、各空間データベースバックエンドで使用できる空間ルックアップの概要を示します。 PostGISラスター(PGRaster)ルックアップは、ラスタールックアップの詳細で説明されている3つのカテゴリに分類されます。ネイティブサポートN
、バイラテラルネイティブサポートB
、およびジオメトリ変換サポート[ X219X] 。
ルックアップタイプ | PostGIS | オラクル | MariaDB | MySQL 5 | SpatiaLite | PGRaster |
---|---|---|---|---|---|---|
:lookup: `bbcontains` | X | X | X | X | N | |
:lookup: `bboverlaps` | X | X | X | X | N | |
:lookup: `contained` | X | X | X | X | N | |
:lookup: `含む ` | X | X | X | X | X | B |
:lookup: `contains_properly` | X | B | ||||
:lookup: `coveredby` | X | X | X | B | ||
:lookup: `covers` | X | X | X | B | ||
:lookup: `crosses` | X | X | X | X | C | |
:lookup: `互いに素な` | 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 | ||
:lookup: `等しい` | X | X | X | X | X | C |
:lookup: `正確 ` | X | X | X | X | X | B |
:lookup: `交差する` | X | X | X | X | X | B |
:lookup: `isvalid` | X | X | X(≥5.7.5) | X(LWGEOM) | ||
:lookup: `重複` | X | X | X | X | X | B |
:lookup: `relate` | X | X | X | X | C | |
:lookup: `same_as` | X | X | X | X | X | B |
:lookup: `touches` | X | X | X | X | X | B |
:lookup: `within` | X | X | X | X | X | B |
:lookup: `left` | X | C | ||||
:lookup: `right` | X | C | ||||
:lookup: `overlaps_left` | X | B | ||||
:lookup: `overlaps_right` | X | B | ||||
:lookup: `overlaps_above` | X | C | ||||
:lookup: `overlaps_below` | X | C | ||||
:lookup: `strictly_above` | X | C | ||||
:lookup: `strictly_below` | X | C |
データベース機能
次の表に、各空間バックエンドで使用できる地理固有のデータベース機能の概要を示します。
関数 | PostGIS | オラクル | MariaDB | 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はこれらの集計をサポートしていないため、表から除外されていることに注意してください。
集計 | PostGIS | オラクル | SpatiaLite |
---|---|---|---|
Collect
|
X | X | |
Extent
|
X | X | X |
Extent3D
|
X | ||
MakeLine
|
X | X | |
Union
|
X | X | X |
脚注
- 1
See Open Geospatial Consortium、Inc。、 OpenGIS Simple Feature Specification For SQL 、Document 99-049(May 5、1999)、atCh。 3.2.5、p。 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の空間制限セクションを参照してください。