MongoDBは組み込みの空間インデックスをサポートしているため、必要なのは、正しい形式を使用してポイントをロードし、空間インデックスを作成してから、クエリを実行することだけです。
簡単な例として、mongoシェルの50州すべての中心点をロードしました。
> db.places.ensureIndex({loc: "2d"})
> db.places.save({name: "AK", loc: {long: -152.2683, lat: 61.3850}})
> db.places.save({name: "AL", loc: {long: -86.8073, lat: 32.7990}})
> db.places.save({name: "AR", loc: {long: -92.3809, lat: 34.9513}})
> db.places.save({name: "AS", loc: {long: -170.7197, lat: 14.2417}})
> ...
次に、指定された場所に最も近い6つのポイントをクエリします。
> db.places.find({loc: { $near: {long: -90, lat: 50}}}).limit(6)
{"name" : "WI", "loc" : { "long" : -89.6385, "lat" : 44.2563 } }
{"name" : "MN", "loc" : { "long" : -93.9196, "lat" : 45.7326 } }
{"name" : "MI", "loc" : { "long" : -84.5603, "lat" : 43.3504 } }
{"name" : "IA", "loc" : { "long" : -93.214, "lat" : 42.0046 } }
{"name" : "IL", "loc" : { "long" : -89.0022, "lat" : 40.3363 } }
{"name" : "ND", "loc" : { "long" : -99.793, "lat" : 47.5362 } }
次に、指定された場所から10km以内のすべてのポイントをクエリします。最も近い州を計算しているので、888km(緯度は約8度)を使用します。
> db.places.find({loc: { $near: {long: -90, lat: 50}, $maxDistance: 8}})
{"name" : "WI", "loc" : { "long" : -89.6385, "lat" : 44.2563 } }
{"name" : "MN", "loc" : { "long" : -93.9196, "lat" : 45.7326 } }
1度の緯度は約111.12kmであるため、アプリケーションではaを使用し$maxDistance: 0.08999
て10kmを表します。
更新デフォルトでは、MongoDBは「理想的な地球平面説」を想定していますが、経度線が極に収束するため、これにより不正確になります。 MongoDBバージョン1.7以降では、球面距離の計算がサポートされており、精度が向上しています。
これは、球面距離を使用して上記のクエリを実行する例です。これmaxDistance
はラジアンであるため、地球の平均半径で割る必要があります。
> db.runCommand({geoNear: "places", near: [-90, 50], spherical: true,
maxDistance: 800/6378});
(summarizing results as they're too verbose to include)
"MN" dis: 0.087..
"WI" dis: 0.100..
"ND" dis: 0.120..