Docs Menu
Docs Home
/
MongoDBマニュアル
/ /

地理空間クエリでレストランを探す

項目一覧

  • Overview
  • ディストーション
  • レストランの検索

MongoDB の地理空間インデックスを使用すると、地理空間の形状とポイントを含むコレクションに対して空間クエリを効率的に実行できます。 このチュートリアルでは、地理空間機能の機能を紹介し、さまざまなアプローチを比較するために、単純な地理空間アプリケーションのクエリを作成するプロセスについて説明します。

このチュートリアルでは、地理空間インデックスの概念を簡単に紹介し、$geoWithin$geoIntersects$nearSphere. を使用してその使用方法を説明します。

ユーザーがニューヨーク市内のレストランを見つけるのに役立つモバイル アプリケーションを設計しているとします。アプリケーションは、次の条件を満たす必要があります。

このチュートリアルでは、2dsphere インデックスを使用して、球面形状上のこのデータを照会します。

球面および平面形状について詳しくは、「地理空間モデル」を参照してください。

球面形状は、地球などの 3 次元の球体を平面に投影する性質上、地図上で視覚化すると歪んで見えます。

たとえば、経度緯度ポイント (0,0)(80,0)(80,80)(0,80) によって定義される球面正方形の仕様を考えます。次の図は、この地域がカバーするエリアを示しています。

球体に投影された正方形の図。
クリックして拡大します

次のリンクからサンプル データセットをダウンロードできます: https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json 。データセットには、それぞれrestaurantsneighborhoodsのコレクションが含まれています。

データセットをダウンロードしたら、データベースにインポートします。

mongoimport <path to restaurants.json> -c=restaurants
mongoimport <path to neighborhoods.json> -c=neighborhoods

地理空間インデックス。ほとんどの場合、$geoWithin および $geoIntersects クエリのパフォーマンスが向上します。

このデータは地理的データであるため、 mongoshを使用して各コレクションに2dsphereインデックスを作成します。

db.restaurants.createIndex({ location: "2dsphere" })
db.neighborhoods.createIndex({ geometry: "2dsphere" })

mongosh: で新しく作成された restaurants コレクションのエントリを調べます。

db.restaurants.findOne()

このクエリは次のようなドキュメントを返します。

{
location: {
type: "Point",
coordinates: [-73.856077, 40.848447]
},
name: "Morris Park Bake Shop"
}

このレストランのドキュメントは、次の図に示す場所に対応しています。

単一の地理空間ポイントのマップ。

チュートリアルでは 2dsphere インデックスを使用するため、location フィールドの形状データは GeoJSON 形式 に従う必要があります。

次に、 neighborhoods コレクションのエントリを調べます。

db.neighborhoods.findOne()

このクエリは、次のようなドキュメントを返します。

{
geometry: {
type: "Polygon",
coordinates: [[
[ -73.99, 40.75 ],
...
[ -73.98, 40.76 ],
[ -73.99, 40.75 ]
]]
},
name: "Hell's Kitchen"
}

この形状は、次の図に示すリージョンに対応します。

地理空間ポリゴンのマップ。
クリックして拡大します

ユーザーのモバイル デバイスがユーザーの現在地をかなり正確に提供できると仮定すると、$geoIntersects を使用してユーザーの現在の近所を簡単に見つけることができます。

たとえば、ユーザーが経度 -73.93414657、緯度 40.82302903 にいるとします。現在の近隣地域を見つけるには、GeoJSON 形式の特別な $geometry フィールドを使用してポイントを指定します。

db.neighborhoods.findOne({ geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } })

このクエリは次の結果を返します。

{
"_id" : ObjectId("55cb9c666c522cafdb053a68"),
"geometry" : {
"type" : "Polygon",
"coordinates" : [
[
[
-73.93383000695911,
40.81949109558767
],
...
]
]
},
"name" : "Central Harlem North-Polo Grounds"
}

特定の地域に含まれるすべてのレストランを検索するクエリを実行することもできます。mongosh で以下を実行して、ユーザーを含む近隣地域を見つけ、その近隣地域内のレストランを数えます。

var neighborhood = db.neighborhoods.findOne( { geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } } )
db.restaurants.find( { location: { $geoWithin: { $geometry: neighborhood.geometry } } } ).count()

このクエリを実行すると、要求された近隣地域に 127 軒のレストランがあることがわかります。これは次の図に示されています。

地理空間ポリゴン内のすべてのレストランのマップ。
クリックして拡大します

特定の地点から指定した距離内にあるレストランを検索するには、$geoWithin$centerSphere を使用して結果を並べ替えずに返すか、結果を距離順に並べ替える必要がある場合は $nearSphere$maxDistance を使用して結果を返します。

円形の領域内のレストランを検索するには、$geoWithin$centerSphere を使用します。$centerSphere は、中心と半径をラジアンで指定して円形領域を表す MongoDB 固有の構文です。

$geoWithin は、ドキュメントを特定の順序で返さないため、ユーザーには最も遠いドキュメントが最初に表示される可能性があります。

次のようにすると、ユーザーから 5 マイル以内にあるすべてのレストランが検索されます。

db.restaurants.find({ location:
{ $geoWithin:
{ $centerSphere: [ [ -73.93414657, 40.82302903 ], 5 / 3963.2 ] } } })

$centerSphereの 2 番目の引数はラジアン単位の半径を受け入れるため、それをマイル単位の地球の半径で割る必要があります。 距離単位の変換の詳細については、「球面ジオメトリを使用した距離の計算」を参照してください。

$nearSphere を使用して、$maxDistance の期間をメートル単位で指定することもできます。これにより、ユーザーから 5 マイル以内にあるすべてのレストランが、最も近いものから最も遠いものの順に並べ替えられて返されます。

var METERS_PER_MILE = 1609.34
db.restaurants.find({ location: { $nearSphere: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] }, $maxDistance: 5 * METERS_PER_MILE } } })

戻る

地理空間クエリ