GeoDjango データベース API¶
空間バックエンド (Spatial Backend)¶
GeoDjango は現在、次の空間データベースバックエンドを提供しています:
django.contrib.gis.db.backends.postgisdjango.contrib.gis.db.backends.mysqldjango.contrib.gis.db.backends.oracledjango.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 固有のジオメトリで、16 進数の 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)}],
... },
... )
空間のルックアップ (Spatial Lookup)¶
GeoDjango's lookup types may be used with any manager method like
filter(), exclude(), etc. However, the lookup types unique to
GeoDjango are only available on spatial fields.
「通常の」フィールド (例えば CharField) のフィルタは、地理情報フィールドのフィルタと連結すできます。ジオメトリルックアップはジオメトリとラスタの両方の入力を受け付けます。
地理情報ルックアップの一般的な構造を以下に記載します。完全なリファレンスは、 空間ルックアップのリファレンス にあります。
ジオメトリ・ルックアップ¶
Geographic queries with geometries take the following general form (assuming
the Zipcode model used in the GeoDjango モデル API):
>>> 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") 。その場合、構文はジオメトリルックアップの構文と同一です。
バンドインデックスを指定するには、ルックアップに追加のパラメータを両側で指定できます。左側では、バンドインデックスを渡すためにダブルアンダースコア構文が使用されます。右側では、ラスターとバンドのインデックスのタプルを指定できます。
This results in the following general form for lookups involving rasters
(assuming the Elevation model used in the
GeoDjango モデル API):
>>> 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 オブジェクトです。バンドインデックスは最初の2つのクエリではデフォルトで 0 に設定され、他のクエリでは 1 に設定されます。
すべての空間ルックアップはラスターオブジェクトの両側で使用できますが、すべての基本演算子がラスター入力をネイティブに受け付けるわけではありません。演算子がジオメトリ入力を想定している場合、ラスタは自動的にジオメトリに変換されます。ルックアップ結果を解釈する際には、この点に留意することが重要です。
ラスターをサポートするタイプは 互換表 のすべてのルックアップにリストされています。ラスタを含むルックアップは現在のところ PostGIS バックエンドでのみ利用可能です。
距離クエリ¶
はじめに¶
Distance calculations with spatial data is tricky because, unfortunately, the Earth is not flat. Some distance queries with fields in a geographic coordinate system may have to be expressed differently because of limitations in PostGIS. Please see the SRID の選択 section for more details.
距離ルックアップ¶
利用可能なDB: PostGIS、MariaDB、MySQL、Oracle、SpatiaLite、PGRaster (ネイティブ)
以下の距離ルックアップが利用できます:
dwithin(MariaDB and MySQL を除く)
注釈
距離をクエリするのではなく、 計測 する場合は Distance 関数を使います。
距離ルックアップは、次のように構成されるタプルパラメータを受け取ります:
計算のベースとなるジオメトリまたはラスター。
距離を含む数字または
Distanceオブジェクト。
Distance オブジェクトが使用されている場合、任意の単位で表現される可能性があります(SQL 生成時には、フィールドの単位に変換された単位が使用される)。それ以外の場合、数値パラメータはフィールドの単位であると想定されます。
注釈
In PostGIS, ST_Distance_Sphere does not limit the geometry types
geographic distance queries are performed with. [3]
However, these queries may take a long time, as great-circle distances must
be calculated on the fly for every row in the query. This is because the
spatial index on traditional geometry fields cannot be used.
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 (3番目のバンド) がルックアップに使用されます。
互換表¶
空間のルックアップ (Spatial Lookup)¶
以下の表は、各空間データベースバックエンドで利用可能な空間ルックアップの概要です。PostGIS Raster (PGRaster) のルックアップは ラスタールックアップの詳細 に記載されている3つのカテゴリに分類されます: ネイティブサポート N、双方向ネイティブサポート B、ジオメトリ変換サポート C。
ルックアップタイプ |
PostGIS |
Oracle |
MariaDB |
MySQL [4] |
SpatiaLite |
PGRaster |
|---|---|---|---|---|---|---|
X |
X |
X |
X |
N |
||
X |
X |
X |
X |
N |
||
X |
X |
X |
X |
N |
||
X |
X |
X |
X |
X |
B |
|
X |
B |
|||||
X |
X |
X (≥ 12.0.1) |
X |
X |
B |
|
X |
X |
X |
X |
B |
||
X |
X |
X |
X |
C |
||
X |
X |
X |
X |
X |
B |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
X |
X |
N |
|
X |
X |
X |
B |
|||
X |
X |
X |
X |
X |
C |
|
X |
X |
X |
X |
X |
B |
|
X |
X (≥ 23c) |
X |
X |
X |
||
X |
X |
X |
X |
X |
B |
|
X |
||||||
X |
X |
X (≥ 12.0.1) |
X |
X |
||
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 |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
||||
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X (LWGEOM/RTTOPO) |
||||
X |
X |
X (≥ 5.1) |
|||
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
X (≥ 12.0.1) |
X |
X (LWGEOM/RTTOPO) |
||
X |
|||||
X |
X (≥ 23c) |
X |
X |
X |
|
X |
X |
X |
X |
X |
|
X |
|||||
X |
X |
X (≥ 12.0.1) |
X |
X |
|
X |
X |
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 |
||||
X |
X |
||||
X |
X |
X |
X |
X |
|
X |
X |
X |
|||
X |
X |
||||
X |
X |
X |
X |
X |
集計関数¶
The following table provides a summary of what GIS-specific aggregate functions are available on each spatial backend.
集計関数 |
PostGIS |
Oracle |
MariaDB |
MySQL |
SpatiaLite |
|---|---|---|---|---|---|
X |
X (≥ 12.0.1) |
X (≥ 8.0.24) |
X |
||
X |
X |
X |
|||
X |
|||||
X |
X |
||||
X |
X |
X |
脚注