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インデックス 」を参照してください。
地理空間インデックスとシャーディングされたコレクション
コレクションをシャーディングする場合、地理空間インデックスをシャードキーとして使用することはできません。 ただし、別のフィールドをシャードキーとして使用して、シャーディングされたコレクションに地理空間インデックスを作成することはできます。
シャーディングされたコレクションでは、次の地理空間操作がサポートされています。
$geoNear集計ステージ$nearと$nearSphereクエリ演算子
$geoWithinと$geoIntersectsを使用して、シャーディングされたクラスターの地理空間データをクエリすることもできます。
カバード クエリ
地理空間クエリ
注意
球面クエリの場合は、 2dsphereインデックス結果を使用します。
球面クエリに2dインデックスを使用すると、北極と南極が入っている球面クエリに2dインデックスを使用するなど、誤った結果が生じる可能性があります。
地理空間クエリ演算子
MongoDB には以下のような地理空間クエリ演算子があります。
名前 | 説明 |
|---|---|
GeoJSON ジオメトリと交差するジオメトリを選択します。2dsphere インデックスは | |
境界となる GeoJSON ジオメトリ内のジオメトリを選択します。2dsphere と 2d インデックスは | |
球面上のポイントに近接する地理空間オブジェクトを返します。地理空間インデックスが必要です。2dsphere と 2d インデックスは |
例を含む詳細については、個々のリファレンス ページを参照してください。
地理空間集約ステージ
MongoDB には、次の地理空間集約パイプライン ステージがあります。
ステージ | 説明 |
|---|---|
例を含む詳細については、$geoNear リファレンス ページを参照してください。
地理空間モデル
MongoDB 地理空間クエリは、平面または球面上のジオメトリを解釈できます。
2dsphere インデックスは球面クエリ(球面上のジオメトリを解釈するクエリ)のみをサポートします。
2d インデックスは平面クエリ(平面上のジオメトリを解釈するクエリ)や、一部の球面クエリをサポートします。2d インデックスは一部の球面クエリをサポートしていますが、これらの球面クエリに 2d インデックスを使用するとエラーが発生する可能性があります。可能であれば、球面クエリには 2dsphere インデックスを使用してください。
次の表は、各地理空間操作で使用される地理空間クエリ演算子とサポートされているクエリを一覧表示したものです。
操作 | 球面/平面クエリ | ノート |
|---|---|---|
球面 |
| |
平面 | ||
| 球面 | GeoJSONポイントと 球面クエリの場合、 |
| 球面 | 代わりに GeoJSONポイントを使用してください。 |
| 球面 | |
| 平面 | |
| 平面 | |
| 平面 | |
| 球面 | |
球面 | ||
球面 | ||
平面 |
Atlas での地理空間クエリの実行
例
次のドキュメントを使用してコレクション 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" } } ] )