これ書いたつもりが書いてなかったか…
メモがあって、速攻アップできそうなので、書いておきます。
  • もともと の経緯としては、運用しているサイトで地図情報をあるベンダーが提供しているAPI経由でデータ取得、表示等を行っていた。
  • そのAPIは日本測地系(ともちょっと違うので、私は「変則日本測地系」って呼んでた)だった。
  • その運用しているサイトでそのベンダーではなく、googlemap apiを使うって話になった。
  • 言わずもがな日本測地系→世界測地系への対応が必要
  • そのサイトでは自分が指定した地点から目的地間の距離が表示される
という感じでした。
わりとぐへええって感じでしたが、point型使えばいけんじゃないかなーって思ってたのでそこまで慌ててませんでした。

で、検証した時のメモから投下しておきます。
  • テーブル
test=# \d+ geo
                                             Table "public.geo"
 Column |  Type   |                    Modifiers                     | Storage  | Stats target | Description
--------+---------+--------------------------------------------------+----------+--------------+-------------
 id     | integer | not null default nextval('geo_id_seq'::regclass) | plain    |              |
 name   | text    |                                                  | extended |              |
 geo    | point   |                                                  | plain    |              |
Has OIDs: no

test=#
  • とりあえずデータつっこむ(データは大体の位置の札幌駅と東京駅)
test=# INSERT INTO geo (name, geo) values ('tokyo', '35.678333,139.768055');
INSERT 0 1
test=# INSERT INTO geo (name, geo) values ('sapporo', '43.065277,141.353611');
INSERT 0 1
test=#
test=# SELECT * FROM geo;
 id |  name   |          geo
----+---------+------------------------
  1 | tokyo   | (35.678333,139.768055)
  2 | sapporo | (43.065277,141.353611)
(2 rows)
  • 配列みたいにデータも取れます(あんまりそういう使い方しないだろうけど)
test=# SELECT name,geo[0] AS latitude, geo[1] AS longitude,geo FROM geo ;
  name   | latitude  | longitude  |          geo
---------+-----------+------------+------------------------
 tokyo   | 35.678333 | 139.768055 | (35.678333,139.768055)
 sapporo | 43.065277 | 141.353611 | (43.065277,141.353611)
(2 rows)

test=#
  • COPYもできる
[postgres@localhost ~]$ head test.csv
3	sendai	38.261721,140.876956
[postgres@localhost ~]$ psql test
psql (9.3.1)
Type "help" for help.

test=# \copy geo FROM ./test.csv
test=#
test=# SELECT * FROM geo;
 id |  name   |          geo
----+---------+------------------------
  1 | tokyo   | (35.678333,139.768055)
  2 | sapporo | (43.065277,141.353611)
  3 | sendai  | (38.261721,140.876956)
(3 rows)
  • んで、二点間の距離。例だと東京駅から
test=# SELECT name,  (geo <-> point(35.678333,139.768055))::float*100 as dist FROM geo;
  name   |       dist
---------+------------------
 tokyo   |                0
 sapporo | 755.519222047143
 sendai  |  281.13261970723
(3 rows)

test=#

100倍してあるのはkmで見やすいようにしているだけです。 ほほう東京<->札幌間755kmくらいかあ… まあ、地球丸いし、ずれてたらごめんなさいって感じです。
また当然これを応用すれば「20km圏内のリストだせや」ってことも対応できますね。

んで、INDEXも貼れるんですが、普通には貼れず、こう貼ります。
test=# CREATE INDEX geo_idx ON geo USING gist(circle(geo,0));
CREATE INDEX
test=#
値に対してではなく、地点Aの位置(0)からの値でINDEXを貼るって感じですね。(あってるかな…)

ここらへんは今無きWEB屋のネタ帳さんのほぼコピペなのですが、WEB屋のネタ帳さんが何故か急に閉鎖してしまったので、残念至極です。

ちょっと改めて見直したいなーって思いました。 

Add Comments

名前
URL
 
  絵文字
 
 

Trackback URL

livedoor プロフィール
Twitter
instagram(SnapWidget)
タグクラウド
  • ライブドアブログ