地理空間クエリ
MongoDB は地理空間データに対するクエリ操作をサポートしています。このセクションでは、MongoDB の地理空間機能を紹介します。
互換性
地理空間クエリは、次の環境でホストされている配置に使用できます。
MongoDB Atlas はクラウドでの MongoDB 配置のためのフルマネージド サービスです
MongoDB Enterprise: サブスクリプションベースの自己管理型 MongoDB バージョン
MongoDB Community: ソースが利用可能で、無料で使用できる自己管理型の MongoDB のバージョン
MongoDB Atlas でホストされている配置では、クエリ Filter バーまたは集計ビルダーを使用して、UI で地理空間クエリを実行できます。詳しくは「Atlas で地理空間クエリを実行する」を参照してください。
地理空間データ
MongoDB では、地理空間データを GeoJSON オブジェクトまたは legacy coordinate pairs として保存できます。
GeoJSON オブジェクト
地球のような球体上の形状を計算するには、位置データを GeoJSON オブジェクトとして保存します。
GeoJSON データを指定するには、以下の埋め込みドキュメントを使用します。
GeoJSON オブジェクトタイプを指定する
type
という名前のフィールドとオブジェクトの座標を指定する
coordinates
というフィールド。
<field>: { type: <GeoJSON type> , coordinates: <coordinates> }
重要
緯度と経度の座標を指定する場合は、最初に経度、次に緯度を指定します。
有効な経度の値は、
-180
以上、180
以下です。有効な緯度の値は
-90
以上、90
以下です。
たとえば、GeoJSONポイントを指定するには、次のようにします。
location: { type: "Point", coordinates: [-73.856077, 40.848447] }
MongoDBでサポートされている GeoJSON オブジェクトのリストと例については、「GeoJSON オブジェクト」を参照してください。
GeoJSON オブジェクトに対する MongoDB の地理空間クエリは球体上で計算されます。MongoDB は、GeoJSON オブジェクトに対する地理空間クエリに WGS84 参照システムを使用します。
Legacy Coordinate Pairs
ユークリッド平面上の距離を計算するには、位置データを legacy coordinate pairs として保存し、 2d
インデックスを使用します。 MongoDB では、データを GeoJSON ポイント 型 に手動で変換する場合に、2dsphere
インデックスを使用して、legacy coordinate pairs での球面計算をサポートします。
データを legacy coordinate pairs として指定するには、配列(推奨)または埋め込みドキュメントのいずれかを使用できます。
- 配列で指定する場合(推奨)
<field>: [ <x>, <y> ] 緯度と経度の座標を指定する場合は、最初に経度、次に緯度を指定します。以下に例を示します。
<field>: [<longitude>, <latitude> ] 有効な経度の値は、
-180
以上、180
以下です。有効な緯度の値は
-90
以上、90
以下です。
- 埋め込みドキュメントを使用して指定する場合
<field>: { <field1>: <x>, <field2>: <y> } 緯度と経度の座標を指定する場合、フィールド名に関係なく、最初のフィールドに経度、2 番目のフィールドに緯度を含む必要があります。以下に例を示します。
<field>: { <field1>: <longitude>, <field2>: <latitude> } 有効な経度の値は、
-180
以上、180
以下です。有効な緯度の値は
-90
以上、90
以下です。
一部の言語では連想マップの順序が保証されないため、legacy coordinate pairs を指定する場合は、埋め込みドキュメントよりも配列の方が推奨されます。
地理空間インデックス
MongoDB には、地理空間クエリをサポートできるように以下の地理空間インデックス型があります。地理空間インデックスの詳細については、「地理空間インデックス」を参照してください。
2dsphere
2dsphere インデックスは、地球のような球体上のジオメトリを計算するクエリをサポートします。
2dsphere
インデックスを作成するには、db.collection.createIndex()
メソッドを使用し、インデックス タイプとして文字列リテラル "2dsphere"
を指定します。
db.collection.createIndex( { <location field> : "2dsphere" } )
<location field>
は、値が GeoJSON オブジェクトまたは legacy coordinates pair のいずれかであるフィールドです。
注意
geoJSON ポイントの配列を含むフィールドにインデックスを作成しようとすると、インデックス構築に失敗し、以下のエラーが返されます。
MongoServerError: Index build failed
2dsphere
インデックスの詳細については、「2dsphere インデックス」を参照してください。
2d
2 dインデックスは、 2 次元平面 上のジオメトリを計算するクエリをサポートします。 インデックスは球体上を計算する$nearSphere
クエリをサポートできますが、可能であれば、球面クエリには2dsphere
インデックスを使用してください。
2d
インデックスを作成するには、db.collection.createIndex()
メソッドを使用して、ロケーション フィールドをキーとして指定し、文字列リテラル "2d"
をインデックス タイプとして指定します。
db.collection.createIndex( { <location field> : "2d" } )
<location field>
は、値が legacy coordinates pair であるフィールドです。
2d
インデックスの詳細については、「2d インデックス」を参照してください。
地理空間クエリ
注意
球状データのクエリに 2d
インデックスを使用すると、誤った結果やエラーが返されることがあります。たとえば、2d
インデックスでは、北極と南極が入っている球面クエリはサポートされていません。
地理空間クエリ演算子
MongoDB には以下のような地理空間クエリ演算子があります。例を含む詳細については、各リファレンスページを参照してください。
名前 | 説明 |
---|---|
注意
時系列コレクションは、2dsphere インデックスに対するクエリからの地理空間データをソートするための $geoNear
集計ステージのみをサポートしています。時系列コレクションでは $near
および $nearSphere
演算子は使用できません。
地理空間集約ステージ
MongoDB には、次の地理空間集約パイプライン ステージがあります。
ステージ | 説明 |
---|---|
地理空間点への近接性に基づいて、順序が付けられたドキュメントのストリームを返します。地理空間データ用の
|
例を含む詳細については、$geoNear
リファレンス ページを参照してください。
地理空間モデル
MongoDB 地理空間クエリは、平面または球面上のジオメトリを解釈できます。
2dsphere
インデックスは球面クエリ(球面上のジオメトリを解釈するクエリ)のみをサポートします。
2d
インデックスは平面クエリ(平面上のジオメトリを解釈するクエリ)や、一部の球面クエリをサポートします。2d
インデックスは一部の球面クエリをサポートしていますが、これらの球面クエリに 2d
インデックスを使用するとエラーが発生する可能性があります。可能であれば、球面クエリには 2dsphere
インデックスを使用してください。
次の表は、各地理空間操作で使用される地理空間クエリ演算子とサポートされているクエリを一覧表示したものです。
操作 | 球面/平面クエリ | ノート |
---|---|---|
球面 | ||
平面 | ||
球面 |
球面クエリの場合、 | |
球面 | 代わりに GeoJSONポイントを使用してください。 | |
$geoWithin : { $geometry : ... } | 球面 | |
$geoWithin : { $box : ... } | 平面 | |
$geoWithin : { $polygon : ... } | 平面 | |
$geoWithin : { $center : ... } | 平面 | |
$geoWithin : { $centerSphere : ... } | 球面 | |
球面 | ||
球面 | ||
平面 |
Atlas での地理空間クエリの実行
Atlas で地理空間クエリを実行するには、 MongoDB Atlas UI を使用します。
インデックスの作成
地理空間コレクションに地理空間インデックスがない場合、作成する必要があります。
コレクションのデータベースを選択します。
メイン パネルと左側の Namespaces には、データベース内のコレクションが一覧表示されます。
コレクションを選択します。
左のパネルまたはメイン パネルで、地理空間データを含むコレクションを選択します。メイン パネルには、 Find 、 Indexes 、 Aggregation のビューが表示されます。
インデックス ビューを選択します。
Index ビューを開くと、Atlas ではコレクションにあるすべてのインデックスが表示されます。
地理タイプのインデックスの定義
Create Index ボタンを押してください。
geo Type インデックスを定義します。 「 GeoJSON オブジェクトのインデックスを作成する方法 」を参照してください。
地理空間データのクエリ
検索ビューを選択します。
地理空間データを含むコレクションから Find タブをクリックして地理空間コレクションを表示します。
クエリを入力します。
Filter テキストボックスにクエリを入力します。いずれかの地理空間クエリ演算子を使用して、地理空間データに対して関連するクエリを実行します。地理空間クエリは、次のようになります。
{ "coordinates": { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [-80.0, 10.00], [ -80.0, 9.00], [ -79.0, 9.0], [ -79.0, 10.00 ], [ -80.0, 10.0 ] ] ] } } } } 適用ボタンを押します。
Apply ボタンを押してクエリを適用します。Atlas は地理空間データをフィルタリングして、地理空間クエリに一致するドキュメントのみを表示します。
MongoDB Atlas UI で地理空間クエリを実行するには、集計パイプラインを作成して実行します。
地理空間クエリ集計パイプラインを作成する
集計ステージを選択します。
左下のパネルの Select ドロップダウンから集計ステージを選択します。
ドロップダウンの右側にあるトグルで、ステージが有効かどうかを指定します。
$geoNear
ステージを使用して、集計パイプラインで地理空間クエリを実行します。集計ステージを入力してください。
ステージに適切な値を入力します。 コメントモードが有効になっている場合、パイプラインビルダは選択したステージの構文ガイドラインを提供します。
ステージを変更すると、Atlasは現在のステージの結果に基づいて右側のプレビュー ドキュメントが更新されます。
$geoNear
ステージは次のようになります。{ near: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, spherical: true, query: { category: "Parks" }, distanceField: "calcDistance" } 必要に応じて、他のパイプライン ステージを実行します。
必要に応じてステージを追加して、集約パイプラインを完了します。
$out
または$merge
を追加して、ビューまたは現在のコレクションに結果を書込み (write) できます。
例
次のドキュメントを使用してコレクション places
を作成します。
db.places.insertMany( [ { name: "Central Park", location: { type: "Point", coordinates: [ -73.97, 40.77 ] }, category: "Parks" }, { name: "Sara D. Roosevelt Park", location: { type: "Point", coordinates: [ -73.9928, 40.7193 ] }, category: "Parks" }, { name: "Polo Grounds", location: { type: "Point", coordinates: [ -73.9375, 40.8303 ] }, category: "Stadiums" } ] )
以下の操作は、location
フィールドに2dsphere
インデックスを作成します。
db.places.createIndex( { location: "2dsphere" } )
上の places
コレクションには 2dsphere
インデックスがあります。以下のクエリは、$near
演算子を使用し、指定された GeoJSONポイントから 1000 ~ 5000 メートル離れたドキュメントを、最も近いものから最も遠いものの順に並べ替えて返します。
db.places.find( { location: { $near: { $geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, $minDistance: 1000, $maxDistance: 5000 } } } )
以下の操作では、$geoNear
集計操作を使用して、クエリフィルター { category:
"Parks" }
に一致するドキュメントを、指定された GeoJSONポイントに最も近いものから最も遠いものの順に並べ替えて返します。
db.places.aggregate( [ { $geoNear: { near: { type: "Point", coordinates: [ -73.9667, 40.78 ] }, spherical: true, query: { category: "Parks" }, distanceField: "calcDistance" } } ] )