Sync all

Webエンジニアの気になる事。困った事もろもろ。

【MongoDB】2d sphere Indexの注意点

非常に困ったのでメモ。

2d sphere Index

2d Indexは以前からあったのですが適切な球面座標を使えてはいませんでした。
メルカトル図法を思い浮かべるといいかもしれません。

f:id:bulbulpaul:20140131215927g:plain

でもこれでは極点に近い点での正確性が損なわれます。

MongoDB 2.4から追加された2d sphere Indexは地理空間インデックスでGeoJSONフォーマットが使えるようになりました。
これにより当然地球は球状なので適切な球面座標を使って検索する事が出来ます。

f:id:bulbulpaul:20140131220318p:plain

このインデックスを設定する事により、$geoWithin, $geoIntersects のクエリが使用できます。

Polygonなら指定の範囲(outer) 内に更に指定の除外範囲(inner)を作れますし非常に便利な機能です。

f:id:bulbulpaul:20140131220114p:plain

$geoWithin, $geoIntersects

今回ハマった点は広範囲の地理空間を指定する際に困った事が起こりました。

db.hoge.find( { field :
                         { $geoWithin :
                            { $geometry :
                               { type : "Polygon" ,
                                 coordinates : [ [ [ 120.0, 40.0 ] , [120.0, 70.0] , [160.0, 70.0], [160.0, 40.0], [120.0, 40.0] ] ]
                      } } } } )

これは通常の$geoWithinの使い方ですので指定条件内のデータが問題なく通ります。

しかし、以下のクエリは問題があります。

db.hoge.find( { field :
                         { $geoWithin :
                            { $geometry :
                               { type : "Polygon" ,
                                 coordinates : [ [ [-120.0, -40.0 ] , [-120.0, 70.0] , [160.0, 70.0], [160.0, -40.0], [-120.0, -40.0] ] ]
                      } } } } )

実行結果は何も帰ってきません。対象データがないと帰ってきます。

理由は、2d sphere Indexの仕様が半球を越える地理空間のクエリは指定出来ない仕様になっています。

これは恐らく二次元球面の考え方に基づいています。

球(sphere)は2つの半球からなり、半球は円盤と同じになります。

f:id:bulbulpaul:20140201004806p:plain

つまり2つの円から形成される仕組みになります。

一つの円(例:北半球)の円の外の位置はもう一つの円(例:南半球)の位置に存在します。

ですので、別の領域内のデータを検索する事が出来ない為では無いかと思います。

ただし、$geoWithin ,$geoIntersectsの半球の制限はどの方向(角度)でも半球の範囲(long:180, lati: 90)以内なら問題無いようです。

そしてもう一点問題が発生しました。

$orが使えない

地球全体(球)の広い範囲では一度にとれない事がわかったので$orで半球と残りの半球で条件を設定すれば問題無いのでは?
と思い実行した所エラーが帰ってきました。

ドキュメントを確認すると$geoWithin ,$geoIntersectsでは$orが使用できない仕様となっています。

結果:一度に半球を越える広範囲の検索は不可能

2d sphere Indexを設定した所には一度に広範囲の検索は不可能と行った結果になりました。

通常の検索、MapReduceのクエリでは2回別々に投げる事になります。

ただ、ソートやLimitの設定が入ってくるとプログラム上で一捻り必要になりそうです。

MongoDBイン・アクション

MongoDBイン・アクション