Sequel を介した PostGIS からのデータ読み出しの基本的なコード
Sequel を介した PostGIS からのデータ読み出しの基本的なコードを入門者向きにまとめました。
かなりはしょっている感じになりますが、まずは最小限の説明をしてみます。
コード
これまでの方法で PostGIS に移した基盤地図情報(道路縁)について、
- その長さが 30 秒以上のレコードを取り出し
- それぞれについて、その幾何情報と「種別」属性を取り出す
という作業をやりたいとします、そのコードは次のとおりになります。
# coding: cp932 require 'rubygems' require 'sequel' DB = Sequel::connect('postgres://fitter:happier@localhost/more_productive', {:encoding => 'SJIS'}) DB[:hatena_rdedg].filter(:ST_Length.sql_function(:the_geom) > 30.0 / 3600). select(:ST_AsText.sql_function(:the_geom), :"種別").each {|r| print "#{r[:"種別"]} #{r[:st_astext]}\n" } DB.disconnect
このコードを出来るだけ詳しく説明します。
- Ruby の定数 DB には、いつもの PostGIS への接続を入れています。接続を開始するときには Sequel::connect を使い、接続を終了するときには、disconnect を使います。
- DB[:hatena_rdedg] は、接続したデータベースの中の、 hatena_rdedg という名前のテーブルを表します。:hatena_rdedg のように、文字列の前に : を付ける表現は、 Ruby のシンボルという情報表現です(資料:プログラミング言語 Ruby リファレンスマニュアル)。
- filter は Sequel のメソッドで、() 内の条件でテーブルの中のデータを絞り込むという意味です。
- :ST_Length.sql_function(:the_geom) は、SQL 関数 ST_Length を、PostGIS のカラム the_geom に適用するという意味です。ここで、ST_Length は PostGIS の関数です。PostGIS については、PostGIS 1.5.1 マニュアル 日本語訳 に良い日本語訳が公開されているので、こちらを参考にするとよいと思います。the_geom は d:id:hfu:20100519 のスクリプトで決めたものですが、幾何情報のカラム名を the_geom にするのはちょっとした「お約束」になっていますので、ふつうは幾何情報は the_geom というカラムに入れます。
- 30.0 / 3600 は、30秒を十進経緯度に直す処理です。
- :ST_Length.sql_function(:the_geom) > 30.0 / 3600 で、「the_geom の長さが 30 秒より大きい」という意味になります。
- DB[:hatena_rdedg].filter(:ST_Length.sql_function(:the_geom) > 30.0 / 3600) は、「テーブル hatena_rdedg から、the_geom の長さが 30秒以上のものを選択する」という意味になります。
- select は Sequel のメソッドで、PostgreSQL (PostGIS) から何を選び出すかを設定する役割を持ちます。
- :ST_AsText.sql_function(:the_geom) は、カラム the_geom に ST_AsText という SQL 関数を適用したもの、という意味になります。ST_AsText は PostGIS の関数で、その仕様はPostGIS 1.5.1 マニュアル 日本語訳 に解説されています。
- :"種別" は、カラム 種別 を指します。ここで、"" を使ったのは Ruby の約束事で、普通 Ruby のシンボルを作るには文字列の前に : を付ければよいのですが、日本語文字列をシンボルにするには、日本語文字列を "" などで括ってから : を付けるのがよいのです。
- select(:ST_AsText.sql_function(:the_geom), :"種別") で、the_geom に ST_AsText を適用したものと、「種別」を選択する、という意味になります。
- each は、Sequel で定義されたメソッドで、これまでに選択した PostGIS のデータを、行ごとに each 以下のブロックに渡してくれます。each は Sequel に限らず Ruby で一般的に用いられる繰り返し処理の方法です。
- DB[:hatena_rdedg].filter(:ST_Length.sql_function(:the_geom) > 30.0 / 3600).select(:ST_AsText.sql_function(:the_geom), :"種別").each {|r| } で、テーブル hatena_rdedg から、長さが 30秒以上のものについてその幾何情報のテキスト表現と属性「種別」を取り出し、それぞれについて r に入れて繰り返せ という意味になります。
- 取り出した結果 r は、Ruby の Hash として渡されます。r[:"種別"] とすることで、属性「種別」を取り出すことができます。
- select で SQL 関数を用いた場合、関数名(PostgreSQL の都合で、すべてを小文字にしたもの)が Hash のキーとなります。r[:st_astext] によって、:ST_AsText.sql_function(:the_geom) の結果を取ることが出来ます。