地理空間で検索する
Overview
このガイドでは、MongoDB Kotlin ドライバーを使用して地理空間データを検索する方法と、MongoDB でサポートされているさまざまな地理空間データ形式を学習できます。
地理空間データとは、地球の表面上の地理的ロケーションを表すデータです。 地理空間データの例には、次のようなものがあります。
映画館のロケーション
国境
自転車走行ルート
ニューヨーク市の犬の運動エリア
地球上の座標
MongoDB に地理空間データを保存してクエリするには、 GeoJSONを使用します。 GeoJSON は、インターネット エンジニアリング タスク 強制(ETF)によって作成されたデータ形式です。
GeoJSON の MongoDB 本社のロケーションは次のとおりです。
"MongoDB Headquarters" : { "type": "point", "coordinates": [-73.986805, 40.7620853] }
GeoJSON の詳細な情報については、 公式 IETF 仕様を参照してください。
GeoJSON の位置
位置は地球上の単一の場所を表し、コード内では 2 つまたは 3 つの数値を含む配列として存在します。
最初の位置の経度(必須)
2 番目の位置の緯度(必須)
3 番目の位置での高度(任意)
重要
経度、次に緯度
GeoJSON では、座標は最初に経度、次に緯度の順に並べられます。地理座標系の規則では、一般に緯度が最初に、経度が 2 番目に記載されているため、これは意外かもしれません。作業に使用する他のツールがどのような形式を使用しているかを必ず確認しましょう。OpenStreetMap や Google マップなどの一般的なツールでは、座標が最初に緯度、次に経度としてリストされます。
GeoJSON タイプ
GeoJSON オブジェクトのタイプによって幾何学的形状が決まります。 幾何学的形状は位置で構成されています。
以下に、一般的な GeoJSON の型と、それらを位置で指定する方法を示します。
Point
: 単一の位置。 This could represent the location of a sculpture.LineString
: 2 つ以上の位置の配列で、一連の線セグメントを形成します。 これは 、中国のすべての国の ルートを表す可能性があります。Polygon
: 最初と最後の位置が同じであるため、スペースを含む位置の配列。 これは バチカン市国内の土地 を表すことができます
MongoDB で使用できる形状の詳細については、 GeoJSON のマニュアル エントリを参照してください。
Index
GeoJSON 形式で保存されたデータをクエリするには、GeoJSON データを含むフィールドを2dsphere
インデックスに追加します。 次のスニペットは、 Indexes
ビルダを使用してlocation.geo
フィールドに2dsphere
インデックスを作成します。
collection.createIndex((Indexes.geo2dsphere("location.geo")))
Indexes
ビルダの詳細については、 インデックス ビルダに関するガイドをご覧ください。
2D 平面上の座標
2 次元ユークリッド平面上の 座標と 座標を使用して地理空間データを保存できます。x
y
2 次元平面上の座標を "legacy coordinate pairs" と呼ばれます。
legacy coordinate pairsは次の構造をしています。
"<field name>" : [ x, y ]
フィールドには 2 つの値の配列が含まれており、1 つ目は x
軸の値を表し、2 つ目は y
軸の値を表している必要があります。
Index
legacy coordinate pairs として保存されたデータをクエリするには、legacy coordinate pairs を含むフィールドを2d
インデックスに追加する必要があります。 次のスニペットは、 Indexes
ビルダを使用してcoordinates
フィールドに2d
インデックスを作成します。
collection.createIndex((Indexes.geo2d("coordinates")))
Indexes
ビルダの詳細については、 インデックス ビルダに関するガイド をご覧ください。
legacy coordinate pairs の詳細については、legacy coordinate pairsに関する MongoDB Server のマニュアル ページを参照してください。
Tip
サポートされている演算子
球面( 2dsphere
)と平面( 2d
)のインデックスは、同じクエリ演算子の一部をサポートしていますが、すべてではありません。 演算子とインデックスの互換性の完全なリストについては、 地理空間クエリ に関するマニュアル エントリを参照してください。
地理空間クエリ
地理空間クエリは、 クエリ演算子 とクエリ パラメータとして GeoJSON シェイプ で構成されます。
クエリ演算子
地理空間データをクエリするには、次のいずれかのクエリ演算子を使用します。
$near
$geoWithin
$nearSphere
$geoIntersects
2DSPHERE インデックスが必要です
これらのクエリ演算子は、MongoDB Kotlin ドライバー内でFilters
ビルダ クラスのnear()
、 geoWithin()
、 nearSphere()
、およびgeoIntersects()
ユーティリティ メソッドを使用して指定できます。
地理空間クエリ演算子の詳細については、地理空間クエリに関するマニュアル エントリを参照してください。
Filters
の詳細については、 フィルター ビルダに関するガイド をご覧ください。
クエリ パラメータ
地理空間クエリで使用する形状を指定するには、MongoDB Kotlin ドライバーのPosition
、 Point
、 LineString
、およびPolygon
クラスを使用します。
MongoDB Kotlin ドライバーで使用できる GeoJSON シェイプの完全なリストについては、 GeoJSON パッケージ を参照してください API ドキュメント。
例
次の例では、MongoDB Atlas サンプル データセットを使用します。 クイック スタート ガイドでは、独自の無料階層 Atlas クラスターをセットアップする方法と、サンプル データセットをロードする方法について学びます。
例では、サンプル データセットの sample_mflix
データベースの theaters
コレクションを使用します。
の例には次のインポートが必要です。
import com.mongodb.client.model.geojson.Point import com.mongodb.client.model.geojson.Polygon import com.mongodb.client.model.geojson.Position import com.mongodb.client.model.Filters.near import com.mongodb.client.model.Filters.geoWithin import com.mongodb.client.model.Projections.fields import com.mongodb.client.model.Projections.include import com.mongodb.client.model.Projections.excludeId
データは、次の Kotlin データ クラスを使用してモデル化されます。
data class Theater( val theaterId: Int, val location: Location ) { data class Location( val address: Address, val geo: Point ) { data class Address( val street1: String, val street2: String? = null, val city: String, val state: String, val zipcode: String ) } }
結果は、次の Kotlin データ クラスを使用してモデル化されます。
data class TheaterResults( val location: Location ) { data class Location( val address: Address ) { data class Address( val city: String ) } }
theaters
コレクションには、 "${Theater::location.name}.${Theater.Location::geo.name}"
フィールドの2dsphere
インデックスがすでに含まれています。
近接性によるクエリ
点に最も近いドキュメントから最も遠いドキュメントの順に検索して返すには、 Filters
ビルダ クラスのnear()
静的ユーティリティ メソッドを使用します。 near()
メソッドは、 $near
クエリ演算子を使用してクエリを構築します。
次の例では、シャード10,000
5,000
フィールドから メートルから メートルの間にある劇場をクエリします。
val database = client.getDatabase("sample_mflix") val collection = database.getCollection<TheaterResults>("theaters") val centralPark = Point(Position(-73.9667, 40.78)) val query = Filters.near( "${Theater::location.name}.${Theater.Location::geo.name}", centralPark, 10000.0, 5000.0 ) val projection = Projections.fields( Projections.include( "${Theater::location.name}.${Theater.Location::address.name}.${Theater.Location.Address::city.name}"), Projections.excludeId() ) val resultsFlow = collection.find(query).projection(projection) resultsFlow.collect { println(it) }
TheaterResults(location=Location(address=Address(city=Bronx))) TheaterResults(location=Location(address=Address(city=New York))) TheaterResults(location=Location(address=Address(city=New York))) TheaterResults(location=Location(address=Address(city=Long Island City))) TheaterResults(location=Location(address=Address(city=New York))) TheaterResults(location=Location(address=Address(city=Secaucus))) TheaterResults(location=Location(address=Address(city=Jersey City))) TheaterResults(location=Location(address=Address(city=Elmhurst))) TheaterResults(location=Location(address=Address(city=Flushing))) TheaterResults(location=Location(address=Address(city=Flushing))) TheaterResults(location=Location(address=Address(city=Flushing))) TheaterResults(location=Location(address=Address(city=Elmhurst)))
$near
演算子の詳細については、 $near の参考ドキュメントを参照してください。
Filters
の詳細については、 フィルター ビルダに関するガイド をご覧ください。
範囲内のクエリ
指定した形状内の地理空間データを検索するには、 Filters
ビルダ クラスのgeoWithin()
静的ユーティリティ メソッドを使用します。 geoWithin()
メソッドは、 $geoWithin
クエリ演算子を使用してクエリを構築します。
次の例では、Long Expression の セクションで映画館を検索します。
val longIslandTriangle = Polygon( listOf( Position(-72.0, 40.0), Position(-74.0, 41.0), Position(-72.0, 39.0), Position(-72.0, 40.0) ) ) val projection = Projections.fields( Projections.include( "${Theater::location.name}.${Theater.Location::address.name}.${Theater.Location.Address::city.name}"), Projections.excludeId() ) val geoWithinComparison = Filters.geoWithin( "${Theater::location.name}.${Theater.Location::geo.name}", longIslandTriangle ) val resultsFlow = collection.find<TheaterResults>(geoWithinComparison) .projection(projection) resultsFlow.collect { println(it) }
TheaterResults(location=Location(address=Address(city=Baldwin)))) TheaterResults(location=Location(address=Address(city=Levittown))) TheaterResults(location=Location(address=Address(city=Westbury))) TheaterResults(location=Location(address=Address(city=Mount Vernon))) TheaterResults(location=Location(address=Address(city=Massapequa)))
次の図は、 longIslandTriangle
変数によって定義される多角形と、クエリによって返された映画館の場所を表すドットを示しています。
$geoWithin
演算子の詳細については、 $geoWithin の参考ドキュメントを参照してください
クエリで使用できる演算子の詳細については、地理空間クエリ演算子 に関する MongoDB サーバーのマニュアル ページ を参照してください。