PHPでのOracle利用(19)──形式指定検索式

戦慄の事実に気がつく。タイトルが統一されてる所為で、何書いたか訳がわからん
仕方ないので今週末は、順次タイトルの修正をすることにする
そもそもカテゴリと内容が微妙に一致していない(php話題が存在しないにも関らずphpカテゴライズされてたり)のが問題だ。書く前と書いた後では意思が違う。そう言うこと
具体的には内容を示すサブタイトルでも取り付けよう。世に広いブログ形式に変えてしまえば楽なのだろうが、そこはそれ。リスクとリターンの天秤だ

さて、いい加減このままチューニングしていても好転しないと遅まきに感じ始めた
よって、高速化は直接的な手法に出よう。現在はジオメトリ情報を空間検索で探し出しWKTにて習得。習得した情報をphpによって文字列分割等を行い《形式》《座標データ》の二つを抽出する解析処理を行っている。要求されていない形式はここで弾かれているという内訳だ
これだとポリゴンのみの要求した場合とラインのみの要求をした場合のループ回転数が全く同じになる
よって現在タイムアウトしている空間範囲での検索は、例え望んでいるのがたった二つPOINTだったとしてもタイムアウトしてしまうのだ
流石にこれはまずい
よってクエリの条件式に空間検索だけではなく、形状検索も付け加えようと企んで見た
要求仕様は一つ。ジオメトリカラムを目標にしてなんとか形状を条件にする

さあ、頑張って見よう

SELECT SDO_UTIL.TO_WKTGEOMETRY(geom) FROM gis_t WHERE 
SDO_FILTER(geom,SDO_UTIL.FROM_WKTGEOMETRY(
'POLYGON ((
137.39095774868213 34.75005318382283,
137.41757782718457 34.75005318382283,
137.41757782718457 34.76906752256343,
137.39095774868213 34.76906752256343,
137.39095774868213 34.75005318382283
))'))='TRUE';

これが今現在発行している空間検索のクエリ──の一例。実際には条件空間は動的に変化する──だ
こいつに新しく条件を付け加えたい

とりあえずジオメトリカラムの仕様を把握する
テーブルに存在するジオメトリカラムをそのままで抽出すると、項目に分かれたデータになっている
その中でSDO_GTYPEという一番初めの四桁数字が形式を表している

・dl00	UNKNOWN_GEOMETRY
・dl01	POINT
・dl02	LINEまたはCURVE
・dl03	POLYGON
・dl04	COLLECTION
・dl05	MULTIPOINT
・dl06	MULTILINEまたはMULTICURVE
・dl07	MULTIPOLYGON
※dとは次元数(2、3あるいは4)。※要するにポリゴンは2003という事

で、SDO_GEOMETRYのメソッドに面白いものを見つけた

Get_Gtype	SDO_GTYPE値に指定された、ジオメトリ・オブジェクトのジオメトリ・タイプを戻します。

実際に試してみよう
こんな簡単な構文を編んでみた

SELECT SDO_GEOMETRY.Get_GType(geom) FROM gis_t WHERE id<3;

で、実行結果は以下のとおり

SDO_GEOMETRY.GET_GTYPE(GEOM)
----------------------------
                           1
                           1

hitしている情報はPOINTのはず
このメソッドは四桁ではなく、下一桁が帰ってくる様子だ。MULTILINEを指定してみたら6が帰ってきた
これで形式を指定した条件式が作成できる。ジオメトリカラム単体が目標だから、汎用性も落ちていない(と願いたい
以下のような構文になった

SELECT SDO_UTIL.TO_WKTGEOMETRY(geom) FROM gis_t WHERE 
SDO_FILTER(geom,SDO_UTIL.FROM_WKTGEOMETRY(
'POLYGON ((
137.39095774868213 34.75005318382283,
137.41757782718457 34.75005318382283,
137.41757782718457 34.76906752256343,
137.39095774868213 34.76906752256343,
137.39095774868213 34.75005318382283
))'))='TRUE' AND SDO_GEOMETRY.Get_GType(geom)=1;

実行結果は…

SDO_UTIL.TO_WKTGEOMETRY(GEOM)
--------------------------------------------------------------------------------
POINT (137.392631542416 34.7681512449333)
POINT (137.398996108983 34.766970194284)
POINT (137.398256644964 34.7672105020236)
POINT (137.399236681549 34.7632753638547)
POINT (137.394549706386 34.7597679897803)
POINT (137.393622007971 34.7600218738271)
POINT (137.391361972267 34.7587117582309)
POINT (137.399583867814 34.7567093879392)
POINT (137.394837771902 34.7531407408202)
─以下省略─

見事戻ってきた。POINTのみの指定も出来ている
条件を詳細にしたお陰で、検索も早い

が、あくまでもこれは少ない情報を求めた場合の高速化である
タイプを区別なく、広範囲に全て求めればあっという間にタイムアウトするのは目に見えている
高速化作業は続く…

・追記
複数のタイプを指定する場合は以下のような形式のクエリを発行した

SELECT SDO_GEOMETRY.Get_GType(geom) FROM gis_t WHERE SDO_FILTER(
geom,SDO_UTIL.FROM_WKTGEOMETRY('POLYGON ((
137.4026040332094 34.758371957011434,
137.4059315426573 34.758371957011434,
137.4059315426573 34.76074874937483,
137.4026040332094 34.76074874937483,
137.4026040332094 34.758371957011434
))'))='TRUE' 
AND (SDO_GEOMETRY.Get_GType(geom)=1 OR 
SDO_GEOMETRY.Get_GType(geom)=7);

括弧が重要
上の例文だとマルチポリゴンとポイントが返される