地理空間情報Webアプリの開発(2)

この記事は1年以上前に書かれました。
内容が古くなっている可能性がありますのでご注意下さい。


地理空間情報を活用したモバイルWebアプリケーションのサーバー環境構築の第2回では、地理空間情報を扱うためにPostgreSQLを拡張したPostGISをAzure上のCentOSにインストールします。

CentOSにPostGISをインストールする方法については、こちらのサイトを参考にします。

はじめに、yumリポジトリの設定を変更します。
/etc/yum.repos.d/CentOS-Base.repo ファイルの[base]セクションと[updates]セクションに

exclude=postgresql*

を追加します。さらに、以下のコマンドを実行して

# curl -O http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-centos93-9.3-1.noarch.rpm
# rpm -ivh pgdg-centos93-9.3-1.noarch.rpm

リポジトリを追加します。EPEL 6リポジトリも必要ですが、前回既に追加してあるので省きます。
以下のコマンドでPostgreSQLとその拡張であるPostGISをインストールし、初期データベースを作成します。

# yum install postgresql93-server postgis2_93
# service postgresql-9.3 initdb

さらに

# service postgresql-9.3 start
# chkconfig postgresql-9.3 on

PostgreSQLを起動し、システムの起動時にPostgreSQLも自動的に起動するよう設定します。

次に、地理空間情報用のデータベースを作成します。

# su - postgres

でpostgresユーザになり、

$ createdb postgis

postgisという名前のデータベースを作成します。

$ psql postgis

psqlコマンドでpostgisデータベースに接続し、

postgres=# CREATE EXTENSION postgis;
postgres=# CREATE EXTENSION postgis_topology;

地理空間情報用の拡張機能をデータベースにインストールします。
ついでにpostgresユーザのパスワードを設定しておきます。

postgres=# alter role postgres password '■■■■';

psqlを終了し、rootユーザに戻り、
/var/lib/pgsql/9.3/data/pg_hba.conf ファイルの

local   all         all                               peer
host    all         all         127.0.0.1/32          ident
host    all         all         ::1/128               ident

local   all         all                               md5
host    all         all         127.0.0.1/32          md5
host    all         all         ::1/128               md5

と変更し、

# service postgresql-9.3 restart

PostgreSQLを再起動します。

次に、地理空間情報のテーブルを作成し、データを投入します。
用いるデータは、横浜オープンデータポータルで公開されている、応急給水拠点です。
ダウンロードしたXMLファイルから、以下のようなCSVファイルを作成しました。

配水池  恩田配水池    青葉区  榎が丘20        35.53907383  139.5113946
配水池  川井配水池    旭区    上川井2556      35.50028808  139.4903702
配水池  鶴ケ峰配水池  旭区    鶴ケ峰本町1197  35.48068913  139.5449766
配水池  中尾配水池    旭区    中尾町2-5      35.46891135  139.5211169
配水池  矢指配水池    旭区    矢指町1227      35.47799959  139.5078896

完全なCSVファイルはこちらにあります。元のXMLファイルのデータにあったNotes要素は省いています。
このデータを投入するためのwatersupplysitesテーブルはpsqlで以下のように定義します。

CREATE TABLE watersupplysites
(
  type character varying(50) NOT NULL,
  name character varying(50) NOT NULL,
  ward character varying(20),
  address character varying(100),
  latitude double precision,
  longitude double precision,
  geog geography,
  CONSTRAINT "PK_WaterSupplySite" PRIMARY KEY (type, name)
);

geography型のカラムgeogは、CSVファイルにはないものです。
psqlで以下のコマンドを実行し、CSVファイルからテーブルにデータを投入します。

\copy watersupplysites(type, name, ward, address, latitude, longitude) from 'watersupplysites.csv';

さらに、以下のコマンドでgeogカラムにデータを投入します。

UPDATE watersupplysites SET geog = ST_Point(longitude, latitude);

数値型で入っている経度と緯度を、ST_Point()関数でgeography型に変換してgeogカラムに格納しています。

データの準備ができましたので、PostGISの空間関係関数を使用したクエリを実行してみます。

ST_DWithin(geography g1, geography g2, double precision d);

は、g1がg2からdメートル以内かどうかを判定します。
そこで、緑区総合庁舎(北緯35.51274191度、東経139.5377387度)から1,000メートル以内の応急給水拠点は以下のクエリで検索することができます。

SELECT name, type, ward FROM watersupplysites WHERE ST_DWithin(geog, ST_Point(139.5377387, 35.51274191), 1000);

実行すると、以下の結果が得られます。

距離を2,000メートルにすると、

件数が増え、緑区の隣の旭区にある応急給水拠点もヒットしました。

地理空間情報Webアプリの開発 1234