Google App Engin (JAVA) でぶち当たった問題 その4

緯度、経緯を利用したGISのアプリの場合、ある地域または区間(メッシュ)に登録されているデータを取り出そうとして通常のSQLであれば

SELECT m FROM Marker WHERE m.lat BETWEEN 36.21 and 24.44 AND m.lng BETWEEN 36.31 and 24.54

で検索を行うことが出来るのですが、BigTableの場合には検索出来ません。

Restrictions on Queries:クエリーの制限規定

上記のGoogle App Enginedドキュメントには”Inequality Filters Are Allowed On One Property Only”
意訳ですが比「較式は一つの属性のみに受つけられます。」 なんだかよくわからない訳ですので。実際にコードを見た方が早いかと思います。

A query may only use inequality filters (<, <=, >=, >) on one property across all of its filters.

たとえば
select from Person where birthYear >= minBirthYearParam
&& birthYear <= maxBirthYearParam
は問題なくBigTableで検索がおこなえます。
なぜなら>=と<=が各一つのみだからです。

こちらは?
select from Person where birthYear >= minBirthYearParam
&& height >= minHeightParam // ERROR

はエラーとなります。
なぜなら>=が2つあるので。

equal (==)についてはその限りではありません。
select from Person where lastName == lastNameParam
&& city == cityParam
&& birthYear >= minBirthYearParam
問題なく処理されます。

もとい

SELECT m FROM Marker WHERE m.lat BETWEEN 36.21 and 24.44 AND m.lng BETWEEN 36.31 and 24.54

を実行する場合にはGeohashアルゴリズムを利用して検索を行うことでBigTableの制限を回避してすることが出来るようです。
http://en.wikipedia.org/wiki/Geohash
JAVAの実装サンプル。
http://code.google.com/p/geospatialweb/source/browse/trunk/geohash/src/Geohash.java?r=104

こんな問題にぶち当たるとやはり・アルゴリズムデザインを再度勉強しなければとつくづく思います。