LCL Engineers' Blog

バス比較なび・格安移動・バスとりっぷを運営する LCLの開発者ブログ

RDBMSに保存された地理情報データをMetabaseのOpenStreetMapで可視化してみる

ご挨拶

技術開発部の杉山です。もうすっかり白髪も増えてきて良い年齢でもあるので、現場からは少し離れマイペースで業務に取り組ませて頂いてます。 これまでは、GAP Japanの立ち上げ時期に関わったり、DELL Japanのコマースサイト立ち上げ、カカクコム等でも色々なサイトの立ち上げに関わりながらエンジニア人生を歩んできました。 どれも楽しい思い出ですが、やはり一番思い出深いのはカカクコム時代に自分で企画して立ち上げさせて頂いたPHOTOHITOです。2008年2月にサイトを立ち上げて、 カカクコムを離れた後も含めて12年以上もカカクコムが運用してくれています。感謝です。 縁あって、現在はカカクコムグループ子会社のLCLにて第2のカカクコムLIFEを過ごさせて頂いているので、微力ながら恩返しを兼ねてグループの成長に貢献したいと思って日々過ごしております。

エンジニアとして

余談ですが、技術開発部のメンバーがアドベントカレンダーで書いたブログを読みつつ資格を取った日々を懐かしく思いました。 資格だけでは意味が無いけど、体系的にきちんと勉強した上で、日常の業務で活用出来れば会社を成長させつつ、個人の成長も楽しむ事が出来るし、 エンジニアとしての市場価値も上がるので、どんどんと勉強しつつ経験を積んでいって頂きたいと思ってます。

techblog.lclco.com

自分の場合は6割位の比率でデータベースを集中的に勉強し、現場でも運用含めて継続的に関わってきました。以下、取得した資格の例です。どれももう古い技術なので現場であまり役に立ちませんが、 1970年にE.F.Codd氏が発表したRDBMS自体はこの50年経った今でも、様々な用途で使い続けられているので、 勉強しながら経験をして来た事は、今でも十分役に立っていると思います。体系立って勉強しつつ、現場で経験しておく事はやはり個人的にはお勧めだと思っています。

MCSE
MCDBA
Oracle Master Platinum 9i
DB2 Engineer
Certified MySQL 5.0 DBA
Certified MySQL 5.0 Developer
CCNA2.0

MetabaseのGIS機能(地理情報システム)の検証

上記の様な経験を通じて、エンジニアとしては常にデータベースを中心に仕事をしてきました。オラクルのMySQLチームでもエンジニアとして仕事をさせて頂いていたのですが、 その時期にリリースされたMySQL5.7, MySQL8.0で地理空間情報を扱うGIS(地理情報システム)関連の機能が充実してきたのが印象的だったのと、 現在の業務の中で、更により具体的で正確なデータや数字をベースにして、会社全体の主観的では無い意思決定を促進して行きたいと思い、普段エンジニア以外の部署のメンバーが意思決定の為に使っているRedashから、 SQLを書かなくても簡単にデータを可視化出来るツールとしてMetabaseを検証している段階でOpenStreetMapが組み込まれている事を知ったので、 データベースに保存されている地理空間情報をMetabaseにて検証し可視化してみる事に致しました。

地理空間情報・GIS(地理情報システム)とは?

地理空間情報とは、地理・空間に関係づけられた情報を指す。「地理情報」、「空間情報」もほぼ同義である。 日本では平成19年8月29日に施行された、地理空間情報活用推進基本法第2条第1項に定義されている用語で、次の情報を指す。 空間上の特定の地点又は区域の位置を示す情報

参照: 地理空間情報 - Wikipedia

地理情報標準は、ISO(国際標準化機構)の地理情報専門委員会ISO/TC211 (Geographic information/Geomatics)にて ISO 19000 シリーズとして国際規格化され、国土地理院の地理情報標準もISO/TC211に準拠している。

参照: https://www.isotc211.org/

地理情報システム(GIS:Geographic Information System)は、地理的位置を手がかりに、位置に関する情報を持ったデータ(空間データ)を総合的に管理・加工し、視覚的に表示し、高度な分析や迅速な判断を可能にする技術である。

参照: GISとは・・・ | 国土地理院

標準化されたGIS機能

先ずは、Metabaseの検証に入る前に、実際に標準化された地理情報をGoogle Map, MySQL, PostgreSQL(PostGIS)にて比較してみます。 LCLのオフィスは今年、勝どきから恵比寿に移転してきたので、検証サンプルとして旧オフィスと新オフィスまでの直線距離を算出してみました。

オフィス 緯度・経度
トリトンスクエア 35.65796, 139.78291
恵比寿ファーストスクエア 35.64753, 139.71478

Google Mapで測定した場合

f:id:oss-rdbms:20201215161526p:plain
Google Mapでの距離測定 合計距離: 6.27 km(3.89 マイル)

MySQLにて算出した場合 (単位:m)

root@localhost [mysql]> select ST_Distance(
    -> ST_GeomFromText('POINT(35.65796 139.78291)',4326),
    -> ST_GeomFromText('POINT(35.64753 139.71478)',4326),'metre') as "from_old_office_to_new_office";
+-------------------------------+
| from_old_office_to_new_office |
+-------------------------------+
|             6277.260893339336 |
+-------------------------------+
1 row in set (0.00 sec)

PostgreSQLにて算出した場合(単位:m)

postgres=# select ST_Distance(
ST_GeomFromText('POINT(139.71478 35.64753)',4326),
ST_GeomFromText('POINT(139.78291 35.65796)',4326),true) as "from_old_office_to_new_office";
 from_old_office_to_new_office 
-------------------------------
                 6277.26149066
(1 行)
結果: 小数点単位の細かい誤差はあるものの、標準化のおかげで同じ結果になりました。

備考:MySQL: 8.0.21 , PostgreSQL: 11.8

MetabaseとOpenStreetMap

バス比較なびにて提供している、バス停情報を活用した検証

Metabaseで地理空間情報を検証するのであれば、バス比較なびで提供させて頂いているバス停情報が最適なサンプルかと思い、 今回は以下のブログで概要を説明してくれている、高橋さんのチームで維持・管理されているバス停情報を活用させて頂きました。

techblog.lclco.com

■ バス比較なびでのバス停情報を表示した場合 (Google Map)

  • ポイントとして、東京駅近郊のバス停を選択しました。

東京駅のバス停一覧 | 高速バス・夜行バス予約【バス比較なび】

f:id:oss-rdbms:20201216122253p:plain

■ Metabaseにて上記データを利用した確認 (OpenStreetMap)

Step❶: 可視化オプションからMAPを選択し、テーブルに含まれるデータを選択

f:id:oss-rdbms:20201216130032p:plain f:id:oss-rdbms:20201216122903p:plain

Step❷: バス停情報に含まれる緯度・経度情報を参照して地図表示

  • MetabaseのGIS機能の一つとして組み込まれているOpenSteetMapにて、バス比較なびでメンテナンスしている緯度・経度情報を基に簡単に地図を表示する事が出来ました。

f:id:oss-rdbms:20201216122653p:plain

参考:空間情報の取得から試して見たい場合

バス関連の交通機関だけで無く、LCLでは飛行機に関しても、最安値で検索可能な格安移動というサイトを2015年12月から運営しています。 格安移動では、地域や空港、駅を細かく指定して、出発地から目的地まで格安に移動できる乗物を検索・比較出来るようになっています。 という事で、検証するなら関連性のある空港関連情報を可視化してみようと思い、国土交通省国土地理院からshapeファイルをダウンロードして可視化して見ました。 カジュアルに試して見たい方の参考になれば幸いです。

f:id:oss-rdbms:20201216193559p:plain

❶ ShapeFileのダウンロード

地球地図日本 | 国土地理院

shinya@ubuntu:~/win/tmp$ wget http://www1.gsi.go.jp/geowww/globalmap-gsi/download/data/gm-japan/gm-jpn-trans_u_2_2.zip
Will not apply HSTS. The HSTS database must be a regular and non-world-writable file.
ERROR: could not open HSTS store at '/home/shinya/.wget-hsts'. HSTS will be disabled.
--2020-12-16 14:50:24--  http://www1.gsi.go.jp/geowww/globalmap-gsi/download/data/gm-japan/gm-jpn-trans_u_2_2.zip
Resolving www1.gsi.go.jp (www1.gsi.go.jp)... 163.42.90.151
Connecting to www1.gsi.go.jp (www1.gsi.go.jp)|163.42.90.151|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://www1.gsi.go.jp/geowww/globalmap-gsi/download/data/gm-japan/gm-jpn-trans_u_2_2.zip [following]
--2020-12-16 14:50:24--  https://www1.gsi.go.jp/geowww/globalmap-gsi/download/data/gm-japan/gm-jpn-trans_u_2_2.zip
Connecting to www1.gsi.go.jp (www1.gsi.go.jp)|163.42.90.151|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 4848845 (4.6M) [application/zip]
Saving to: ‘gm-jpn-trans_u_2_2.zip’

gm-jpn-trans_u_2_2.zip                  100%[=============================================================================>]   4.62M  3.02MB/s    in 1.5s

2020-12-16 14:50:26 (3.02 MB/s) - ‘gm-jpn-trans_u_2_2.zip’ saved [4848845/4848845]

shinya@ubuntu:~/win/tmp$

❷ ダウンロードしたファイルの展開

root@ubuntu:/mnt/c/Linux/tmp# unzip gm-jpn-trans_u_2_2.zip
Archive:  gm-jpn-trans_u_2_2.zip
  inflating: gm-jpn-trans_u_2_2/airp_jpn.dbf
  inflating: gm-jpn-trans_u_2_2/airp_jpn.prj
  inflating: gm-jpn-trans_u_2_2/airp_jpn.shp
  inflating: gm-jpn-trans_u_2_2/airp_jpn.shx
  inflating: gm-jpn-trans_u_2_2/ferryl_jpn.dbf
  inflating: gm-jpn-trans_u_2_2/ferryl_jpn.prj
  inflating: gm-jpn-trans_u_2_2/ferryl_jpn.shp
  inflating: gm-jpn-trans_u_2_2/ferryl_jpn.shx
  inflating: gm-jpn-trans_u_2_2/portp_jpn.dbf
  inflating: gm-jpn-trans_u_2_2/portp_jpn.prj
  inflating: gm-jpn-trans_u_2_2/portp_jpn.shp
  inflating: gm-jpn-trans_u_2_2/portp_jpn.shx
  inflating: gm-jpn-trans_u_2_2/raill_jpn.dbf
  inflating: gm-jpn-trans_u_2_2/raill_jpn.prj
  inflating: gm-jpn-trans_u_2_2/raill_jpn.shp
  inflating: gm-jpn-trans_u_2_2/raill_jpn.shx
  inflating: gm-jpn-trans_u_2_2/roadl_jpn.dbf
  inflating: gm-jpn-trans_u_2_2/roadl_jpn.prj
  inflating: gm-jpn-trans_u_2_2/roadl_jpn.shp
  inflating: gm-jpn-trans_u_2_2/roadl_jpn.shx
  inflating: gm-jpn-trans_u_2_2/rstatp_jpn.dbf
  inflating: gm-jpn-trans_u_2_2/rstatp_jpn.prj
  inflating: gm-jpn-trans_u_2_2/rstatp_jpn.shp
  inflating: gm-jpn-trans_u_2_2/rstatp_jpn.shx
  inflating: gm-jpn-trans_u_2_2/trans_jpn.met
root@ubuntu:/mnt/c/Linux/tmp#

❸ 空港に関してのPOINTデータが入っているので先ずはshapeファイルからSQLを作成

shinya@ubuntu:~/win/tmp/gm-jpn-trans_u_2_2$ shp2pgsql -s 4326 -D -i -I -W utf8 airp_jpn.shp > airport.sql
Shapefile type: Point
Postgis type: POINT[2]

❹ 作成したファイルをデータベースに取り込む

shinya@ubuntu:~/win/tmp/gm-jpn-trans_u_2_2$ psql -h 192.168.193.200 -U postgres GIS < airport.sql
Password for user postgres:
SET
SET
BEGIN
CREATE TABLE
ALTER TABLE
                 addgeometrycolumn
---------------------------------------------------
 public.airp_jpn.geom SRID:4326 TYPE:POINT DIMS:2
(1 row)

COPY 92
CREATE INDEX
COMMIT
ANALYZE
shinya@ubuntu:~/win/tmp/gm-jpn-trans_u_2_2$

❺ Metabaseで直接見ると、Geometryデータとして入っているのでMetabaseと言えどもそのままでは地図表示出来ないので関数で緯度経度を取り出して上げます。

f:id:oss-rdbms:20201216194615p:plain

select iko,ita,nam,
ST_X(ST_Centroid(ST_Transform(geom, 4326))) AS long,
ST_Y(ST_Centroid(ST_Transform(geom, 4326))) AS lat
from airp_jpn;
  • 変換してあげると、以下の様に緯度・経度を分割して表示可能です。 f:id:oss-rdbms:20201216200157p:plain

❻ Metabaseにて、ビジュアライゼーションしてあげるとOpenStreepMapに日本の空港が全て網羅されている事が確認出来ます。

f:id:oss-rdbms:20201216193318p:plain

補足:MySQLでShapeFileを取り込む場合

今回は、師走真っただ中という事で、時間が取れず検証する事は出来ませんでしたが、 MySQLでShapeファイルを取り込む方法に関しては、Oracle MySQLチームの山﨑さんのGitを参考にしてみて下さい。 github.com

最後に

最後までお読み頂き、有難うございました!! 今後は、これらの地理空間情報と色々なデータを組み合わせて、より良い意思決定やサービス作りに活かせるように、 データ活用を促進していきたいと思っています。

  • おまけ

水平位置を求める歴史 (日本:大化の改新の地籍測量~)

Geofabrik GmbH (グローバルに様々な空間情報をダウンロード出来て便利)

2020年は特に変化の大きな年でした。 もう年末ですので、健康を大切にして素敵な年末年始をお迎えください!!