こんにちは。クライアントチームサーバサイドエンジニア、コウです。
前回 Part 1 で、何故 PostgreSQL に決めたかについて書きました。
Part 2 においては、2つの空間データ型について簡単に紹介します。
※ 開発環境: macOS Sierra 10.12.5, PostgreSQL 9.6.3, PostGIS 2.3.2
2つの空間データ型
PostgreSQL のインストール方法 と PostGIS のインストール方法と、PostgreSQL ユーザー周りの設定はスキップさせてください。
MacOS だと、両方のインストールは homebrew で簡単に行なえます。
インストール及び設定ができたら、ターミナルに psql
で \dx
を実行し、PostGISのバージョンを確認しましょう。
ref: macOS で PostGIS のインストールと設定の方法
Name | Version | Schema | Description ---------+---------+------------+--------------------------------------------------------------------- postgis | 2.3.2 | public | PostGIS geometry, geography, and raster spatial types and functions
Description に 書いてある geometry 型 と geography 型 は、今回の実装に関わる大事な空間データ型(Spatial Data Types)です。
もちろん、PostGISはほかの空間データ型もサポートしていますが、geometry 型と geography 型は基本中の基本です。
- geometry 型 は平面(Planar)空間データ型です。geometry 型のメソッドで緯度経度から2点間の距離を計測した結果の単位は度(°)です。
- geography 型 は回転楕円体(Ellipsoidal)空間データ型です。デフォルトSRID(空間参照系)は4326。geography 型のメソッドで緯度経度から2点間の距離を計測した結果の単位はメートル(m) です。
空間参照系(SRID)
SRID-4326 について、私はあまり詳しくないので、こちらの記事「空間参照系の概要」を参考してください。
デフォルトのgeometry 型にはSRIDがない(0)です。
なので、緯度経度計測する時に、SRIDを4326にしないと、結果が少々変わります。
私みたいにSRIDがあんまりわからない方々は、何も考えずにデフォルトのままにしてもいいと思います。
2つの型を使って計測してみる
両型共通なメソッド ST_Distance
を使って、東京駅(Lat: 35.681167, Lng: 139.767052)と横浜駅(Lat: 35.465786, Lng: 139.622313)間の距離を計測して、 geometry と geography の違いを説明します。
まず、緯度経度をWKT (Well-known text) 形式にして:
- 東京駅
POINT(139.767052 35.681167)
- 横浜駅
POINT(139.622313 35.465786)
つぎに、2つのファンクション ST_GeomFromText と ST_GeogFromText でWKTを geometry と geography に変換しないといけないです。
最後はSQLの実行です。
geometry の SQL
SELECT ST_Distance( ST_GeomFromText('POINT(139.767052 35.681167)'), ST_GeomFromText('POINT(139.622313 35.465786)') );
実行結果は 0.259496345411655 度 です。
ST_Distance の日本語ドキュメントにおいて:
ジオメトリ型については、二つのジオメトリの、2次元の最小デカルト距離 (空間参照系に基づきます)を、投影法の単位で返します。
なので、ここでデカルト距離の計算式で検証してみました。
結果はバッチリですが、メートルへ変換しないと使えなさそうです。
geography のSQL
SELECT ST_Distance( ST_GeogFromText('POINT(139.767052 35.681167)'), ST_GeogFromText('POINT(139.622313 35.465786)') );
実行結果は 27261.54830124 メートル です。
ジオグラフィ型については、デフォルトでは、二つのジオメトリ間の測地距離をメートル単位で返します。
国土地理院のツールで結果を検証してみます。
geography での計算結果もバッチリです〜
キミにきめた!
geometry と geography は異なった空間型なので、使えるファンクションも多少違います。
PostGIS のドキュメントにファンクションサポート一覧テーブルがあります: PostGIS Function Support Matrix 。
テーブルから見ると、 geometry のファンクションは geography のよりだいぶ多く、
geometry のCPU実行時間は geography より短いです。
でも、どちらにするか、プロジェクトの仕様により、選びましょう。
(PostGIS ドキュメントからのアドバイス:When to use Geography Data type over Geometry data type
)
今回の仕様は「ユーザーの緯度経度から半径nキロメートル内のマーカーを取得する」なので、geography 型は相応しいです。
というわけで、今回マーカーデータのテーブルの型は geography にしましょう。
次回の Part 3 から、Rails に突入します。
皆さんお楽しみにしてくださいね〜(<ゝω・)☆
document refs: PostGIS 2.3.3dev Manual, PostGIS 2.4.0dev マニュアル
(/・ω・)/ ★☆★☆★ サーバサイドエンジニア大絶賛募集中 ★☆★☆★ \(・ω・\)