Google MapsとMySQLの連携
こんにちは、アシアルの中川です。
Google Mapsに表示する情報をMySQLのgeometry型で扱う方法を試してみました。
Google Mapsのある地点にマーカーを表示したりすることがある場合、
緯度・経度の情報で地点に表示させることができますが、
データベースにこの情報を保存する場合、lat(float), lng(float)とそれぞれカラムに保存する方法もあるのですが、この方法では各データの位置の関係が非常に扱いにくくなります。
Google Mapsで表示されている範囲内のデータのみ取得したい場合や、
ある地点から近い順に取得する場合などに面倒なことになります。
そこで、MySQL4.1以降で用意されている空間情報を扱う機能の「geometry」型を使用します。
「MySQL 4.1 リファレンスマニュアル :: 10 MySQL における空間情報の機能(日本語)」
「MySQL :: MySQL 5.0 Reference Manual :: 11.12 Spatial Extensions(英語)」
「MySQL :: MySQL 5.1 リファレンスマニュアル :: 16 Spatial Extensions(英語)」
※今回紹介する方法は、「鉄道模型のコミュニティ『トレイン・トレイン』」にて
先日リリースしたコンテンツ「鉄マップ」にも使用してみました。
テーブルの作成ですが、空間情報を扱うカラムの型を「geometry」と指定します。
空間情報用のカラムにインデックスを作成するためには、「InnoDB」でなく「MyISAM」を使用し、
「SPATIAL」キーワードを使いインデックスを作成します。
また、対象のカラムが「NOT NULL」宣言がされている必要があるようです。
これで、準備ができました。次にデータを登録してみましょう。
通常のINSERT文の発行で行えるのですが、geometry型のカラムにデータを入れるためには、変換用に用意されている関数「GeomFromText」を使用します。
緯度経度を取り出すときには関数(X, Y, AsTextなど)を使用し、以下のように変換して取得することができます。
データベースの準備ができたところで、次はGoogle Maps側です。
Google Mapsで表示しているエリアの情報を以下のように取得できます。
JavaScriptで取得したデータをAjaxなどでサーバに投げてやります。
取得するタイミングは以下のようにイベント発生のタイミング等指定できます。
以上のようにGoogle MapsなどからAjaxでサーバ側に送信した地点や、範囲などの情報を使う際に、MySQLの「geometry」型の威力が発揮されます。
Ajax送信やサーバ側の受信のコードはここでは、触れませんが以下のSQLと組み合わせれば簡単に実装できるでしょう。
※サンプルデータは以下を使用
■2点間の距離の近い順に5件取得する。(ここではアシアルの緯度経度から近い順)
■指定した範囲内のデータを取得する。(ここでは東京周辺の範囲のみ)
このように、通常のカラム型で保存した場合と違い、位置情報を有効に使用することができます。
まだ、2つのPOINT間の最短距離を返してくれる、Distanceなどの関数は使えないようですが、
マニュアルを見る限りでは、将来的にはサポートされるようです。
パフォーマンス等については、まだ私のほうでは未検証ですが、
位置情報を扱うには非常に簡単に扱えますので、ぜひ試してみてはいかがでしょう。
[補足]PostgreSQLでも位置情報を扱うことができ、PostGISやPostLBSなどのさらに便利な感じのものもあります。
Google Mapsに表示する情報をMySQLのgeometry型で扱う方法を試してみました。
Google Mapsのある地点にマーカーを表示したりすることがある場合、
緯度・経度の情報で地点に表示させることができますが、
データベースにこの情報を保存する場合、lat(float), lng(float)とそれぞれカラムに保存する方法もあるのですが、この方法では各データの位置の関係が非常に扱いにくくなります。
Google Mapsで表示されている範囲内のデータのみ取得したい場合や、
ある地点から近い順に取得する場合などに面倒なことになります。
そこで、MySQL4.1以降で用意されている空間情報を扱う機能の「geometry」型を使用します。
「MySQL 4.1 リファレンスマニュアル :: 10 MySQL における空間情報の機能(日本語)」
「MySQL :: MySQL 5.0 Reference Manual :: 11.12 Spatial Extensions(英語)」
「MySQL :: MySQL 5.1 リファレンスマニュアル :: 16 Spatial Extensions(英語)」
※今回紹介する方法は、「鉄道模型のコミュニティ『トレイン・トレイン』」にて
先日リリースしたコンテンツ「鉄マップ」にも使用してみました。
テーブルの作成ですが、空間情報を扱うカラムの型を「geometry」と指定します。
- CREATE
TABLE `spot` ( `id` int(10) unsigned NOT NULL auto_increment, `name` varchar(255) NOT NULL, `latlng` geometry NOT NULL, `zoom` tinyint(2) unsigned default NULL, PRIMARY KEY (`id`), SPATIAL KEY `spot_latlng_index` (`latlng`) - )
ENGINE=MyISAM;
空間情報用のカラムにインデックスを作成するためには、「InnoDB」でなく「MyISAM」を使用し、
「SPATIAL」キーワードを使いインデックスを作成します。
また、対象のカラムが「NOT NULL」宣言がされている必要があるようです。
これで、準備ができました。次にデータを登録してみましょう。
通常のINSERT文の発行で行えるのですが、geometry型のカラムにデータを入れるためには、変換用に用意されている関数「GeomFromText」を使用します。
- mysql>
INSERT INTO `spot` (`name`, `latlng`, `zoom`) VALUES ('アシアル株式会社', GeomFromText('POINT(139.762522 35.706752)'), 19); - mysql>
SELECT * FROM spot; - +----+--------------------------+---------------------------+------+
- |
id | name | latlng | zoom | +----+--------------------------+---------------------------+------+ - |
1 | アシアル株式会社 | @`xa@ | 19 | - +----+--------------------------+---------------------------+------+
緯度経度を取り出すときには関数(X, Y, AsTextなど)を使用し、以下のように変換して取得することができます。
- mysql>
SELECT id, name, X(latlng) as lng, Y(latlng) as lat, zoom, AsText(latlng) as geomtext FROM spot; - +----+--------------------------+------------+-----------+------+-----------------------------+
- |
id | name | lng | lat | zoom | geomtext | - +----+--------------------------+------------+-----------+------+-----------------------------+
- |
1 | アシアル株式会社 | 139.762522 | 35.706752 | 19 | POINT(139.762522 35.706752) | - +----+--------------------------+------------+-----------+------+-----------------------------+
データベースの準備ができたところで、次はGoogle Maps側です。
- var
lat = 35.706752; - var
lng = 139.762522; - var
zoom = 19; - //マップを作成し、中央を指定位置にセットする。
- var
map = new GMap2(document.getElementById("map-canvas")); - map.setCenter(new
GLatLng(lat, lng), zoom); - map.addControl(new
GLargeMapControl()); - map.addControl(new
GMapTypeControl()); - map.addMapType(G_SATELLITE_3D_MAP);
- //指定位置にマーカーをセットする。
- var
marker = new GMarker(new GLatLng(lat, lng)); - map.addOverlay(m);
Google Mapsで表示しているエリアの情報を以下のように取得できます。
- var
options = {}; - //センターとズーム情報取得
- var
center = map.getCenter(); - options['lng']
= center.lng(); - options['lat']
= center.lat(); - options['zoom']
= map.getZoom(); - //表示範囲情報
- var
latlngbounds = map.getBounds(); - var
sw = latlngbounds.getSouthWest(); - var
ne = latlngbounds.getNorthEast(); - options['bounds[swlat]']
= sw.lat(); //南西の緯度 - options['bounds[swlng]']
= sw.lng(); //南西の経度 - options['bounds[nelat]']
= ne.lat(); //北東の緯度 - options['bounds[nelng]']
= ne.lng(); //北東の経度
JavaScriptで取得したデータをAjaxなどでサーバに投げてやります。
取得するタイミングは以下のようにイベント発生のタイミング等指定できます。
- GEvent.addListener(map,
'dragend', function(){ //マップのドラッグ移動終了後 // ここで位置・範囲取得やajax等の処理をする - });
- GEvent.addListener(map,
'zoomend', function(){ //マップのズーム変更終了後 // ここで位置・範囲取得やajax等の処理をする - });
以上のようにGoogle MapsなどからAjaxでサーバ側に送信した地点や、範囲などの情報を使う際に、MySQLの「geometry」型の威力が発揮されます。
Ajax送信やサーバ側の受信のコードはここでは、触れませんが以下のSQLと組み合わせれば簡単に実装できるでしょう。
※サンプルデータは以下を使用
- mysql>
SELECT id, name, X(latlng) as lng, Y(latlng) as lat, zoom, AsText(latlng) as geomtext FROM spot; - +----+--------------------------+------------+-----------+------+-----------------------------+
- |
id | name | lng | lat | zoom | geomtext | - +----+--------------------------+------------+-----------+------+-----------------------------+
- |
1 | アシアル株式会社 | 139.762522 | 35.706752 | 19 | POINT(139.762522 35.706752) | - |
2 | 東京ドーム | 139.752016 | 35.705567 | 18 | POINT(139.752016 35.705567) | - |
3 | 東京タワー | 139.745423 | 35.658582 | 18 | POINT(139.745423 35.658582) | - |
4 | 大阪駅 | 135.29 | 34.42 | 16 | POINT(135.29 34.42) | - |
5 | 名古屋 | 136.54 | 35.11 | 16 | POINT(136.54 35.11) | - |
6 | 那覇市 | 127.41 | 26.13 | 16 | POINT(127.41 26.13) | - +----+--------------------------+------------+-----------+------+-----------------------------+
- 6
rows in set (0.00 sec)
■2点間の距離の近い順に5件取得する。(ここではアシアルの緯度経度から近い順)
- mysql>
SELECT -> id, name, X(latlng) as lng, Y(latlng) as lat, zoom, -> GLength(GeomFromText(CONCAT('LineString(139.762522 35.706752,', X(latlng), ' ', Y(latlng),')'))) AS len -> FROM spot ORDER BY len; - +----+--------------------------+------------+-----------+------+-------------------+
- |
id | name | lng | lat | zoom | len | - +----+--------------------------+------------+-----------+------+-------------------+
- |
1 | アシアル株式会社 | 139.762522 | 35.706752 | 19 | 0 | - |
2 | 東京ドーム | 139.752016 | 35.705567 | 18 | 0.010572618455228 | - |
3 | 東京タワー | 139.745423 | 35.658582 | 18 | 0.051114818800422 | - |
5 | 名古屋 | 136.54 | 35.11 | 16 | 3.2773100234778 | - |
4 | 大阪駅 | 135.29 | 34.42 | 16 | 4.6539428176534 | - |
6 | 那覇市 | 127.41 | 26.13 | 16 | 15.63006649474 | - +----+--------------------------+------------+-----------+------+-------------------+
- 6
rows in set (0.00 sec)
■指定した範囲内のデータを取得する。(ここでは東京周辺の範囲のみ)
- mysql>
SELECT id, name, X(latlng) as lng, Y(latlng) as lat, zoom -> FROM spot -> WHERE MBRContains(GeomFromText('LineString(140.05508422851562 36.00134056648952, 139.20089721679688 35.55345722493522)'), latlng); - +----+--------------------------+------------+-----------+------+
- |
id | name | lng | lat | zoom | - +----+--------------------------+------------+-----------+------+
- |
1 | アシアル株式会社 | 139.762522 | 35.706752 | 19 | - |
2 | 東京ドーム | 139.752016 | 35.705567 | 18 | - |
3 | 東京タワー | 139.745423 | 35.658582 | 18 | - +----+--------------------------+------------+-----------+------+
- 3
rows in set (0.00 sec)
このように、通常のカラム型で保存した場合と違い、位置情報を有効に使用することができます。
まだ、2つのPOINT間の最短距離を返してくれる、Distanceなどの関数は使えないようですが、
マニュアルを見る限りでは、将来的にはサポートされるようです。
パフォーマンス等については、まだ私のほうでは未検証ですが、
位置情報を扱うには非常に簡単に扱えますので、ぜひ試してみてはいかがでしょう。
[補足]PostgreSQLでも位置情報を扱うことができ、PostGISやPostLBSなどのさらに便利な感じのものもあります。
コメント
コメントフォーム
トラックバック
最近の記事
- もうすぐ健康診断があるんだ・・・ [2010年09月02日 : 阿部恵]
- Photoshopで壁紙を作りながら、基本的な使い方を覚える [2010年09月01日 : 鴨田健次]
- はじめての共同作業 Canvas編 (node.js + websocket) [2010年09月01日 : 中川善樹]
- 「PHP×Flex(後編)」PHPテクニカルセミナー(無料)第4弾の募集を開始しました!! [2010年08月26日 : 和田記光]
- 【HTML5】Canvasでお絵かきしてみた(前編) [2010年08月25日 : 橋本章史]
- MacにgroongaのMySQL用ストレージエンジン [2010年08月23日 : 笹亀弘]
- Appleのサイトで見たiPhone4をFireworksで描いてみました-1/2 [2010年08月19日 : 和田記光]
- iPad版の会社紹介を作ってみました [2010年08月19日 : 小林有佳]
- iPhoneアプリ開発開始時に気をつけるべきファイルの取り扱い (2) [2010年08月19日 : 亀本大地]
- symfonyセミナー動画無料公開! [2010年08月13日 : 岡本雄樹]



レンタルサーバで同じことを試してみて、
何かに使えるなあと思いました。
ところで、
登録したデータをphpmyadminでエクスポートしようとすると、
文字化けしてしまいlatlngが使えないデータになってしまいました。
コマンドだと問題ないでしょうか。
このままだとあとでデータを流用したいとき不便ですね。