Overview
このガイドでは、 Scalaドライバーを使用して地理空間データをクエリする方法を学習できます。 MongoDBでサポートされているさまざまな地理空間データ形式についても学習できます。
地理空間データは、地球の表面上の地理的ロケーションを表します。地理空間データの例には、次のようなものがあります。
映画館のロケーション
国境
自転車走行ルート
ニューヨーク市の犬の運動エリア
サンプル データ
theaterssample_mflixこのガイドの例では、Atlasサンプルデータセット の データベースの コレクションを使用します。Scalaアプリケーションからこのコレクションにアクセスするには、Atlas クラスターに接続する MongoClient を作成し、database 変数と collection 変数に次の値を割り当てます。
val database: MongoDatabase = mongoClient.getDatabase("sample_mflix") val collection: MongoCollection[Document] = database.getCollection("theaters")
MongoDB Atlasクラスターを無料で作成して、サンプルデータセットをロードする方法については、MongoDBを使い始めるガイドを参照してください。
地球上の座標
MongoDB に地理空間データを保存してクエリするには、 GeoJSONを使用します。 GeoJSON は、インターネット エンジニアリング タスク 強制(ETF)によって作成されたデータ形式です。
GeoJSON の MongoDB 本社のロケーションは次のとおりです。
"location" : { "type": "Point", "coordinates": [-73.986805, 40.7620853] }
GeoJSON に関する明確な情報については、公式 IETF 仕様 を参照してください。
GeoJSON の位置
位置は地球上の単一の場所を表し、2 つまたは 3 つの数値を含む配列として与えられます。
最初の位置の経度(必須)
2 番目の位置の緯度(必須)
3 番目の位置での高度(任意)
重要
経度、次に緯度
GeoJSON では、座標は最初に経度、次に緯度の順に並べられます。地理座標系の規則では、一般に緯度が最初に、経度が 2 番目に記載されているため、これは意外かもしれません。作業に使用する他のツールがどのような形式を使用しているかを必ず確認しましょう。OpenStreetMap や Google マップなどの一般的なツールでは、座標が最初に緯度、次に経度としてリストされます。
GeoJSON タイプ
GeoJSON オブジェクトのタイプによって幾何学的形状が決まります。 幾何学的形状は位置で構成されています。
以下に、一般的な GeoJSON の型と、それらを位置で指定する方法を示します。
Point: 単一の位置。これは暗号化の場所を表すことができます。LineString: 2 つ以上の位置の配列。これにより、一連の線セグメントを形成します。これは、中国のすべての国のルートを表す可能性があります。Polygon: 最初と最後の位置が同じで、スペースを含む位置の配列。これは バチカン市国内の土地 を表すことができます
MongoDBで使用できる形状の詳細については、サーバー マニュアルの GeoJSON を参照してください。
Index
2dsphereインデックスを作成するには、 Indexes.geo2dsphere()ヘルパーを使用して2dsphereインデックスの仕様を作成します。 仕様をMongoCollection.createIndex()メソッドに渡してインデックスを作成します。
次の例では、 theatersコレクションの"location.geo"フィールドに2dsphereインデックスを作成します。
val indexObservable = collection.createIndex(Indexes.geo2dsphere("location.geo")) Await.result(indexObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
Scalaドライバーのインデックスについて詳しくは、「 インデックスを使用してクエリを最適化する 」ガイドを参照してください。
2D 平面上の座標
2 次元ユークリッド平面上の 座標と 座標を使用して地理空間データを保存できます。 2x 次元平面上の座標は、y レガシー coordinate pairs と呼ばれます。
legacy coordinate pairsは次の構造をしています。
{ "location" : [ x, y ] }
フィールド値には 2 つの値の配列が含まれており、1 つ目は x 軸の値を表し、2 つ目は y 軸の値を表します。
Index
レガシー coordinate pairs として保存されたデータをクエリするには、 レガシー coordinate pairs を含むフィールドを 2dインデックスに追加する必要があります。次のスニペットは、Indexesオブジェクトを使用して coordinatesフィールドに 2dインデックスを作成します。
val indexObservable = collection.createIndex(Indexes.geo2d("coordinates")) Await.result(indexObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
Scalaドライバーのインデックスについて詳しくは、「 インデックスを使用してクエリを最適化する 」ガイドを参照してください。
レガシー coordinate pairs の詳細については、サーバー マニュアルの地理空間クエリガイドのレガシー coordinate pairsセクションを参照してください。
Tip
サポートされている演算子
球面(2dsphere)と平面(2d)インデックスは、同じクエリ演算子の一部をサポートしていますが、すべてではありません。演算子とそのインデックスの互換性の完全なリストを表示するには、サーバー マニュアルの「地理空間クエリガイド」の地理空間クエリ演算子セクションを参照してください。
地理空間クエリ
地理空間クエリは、 クエリ演算子 とクエリ パラメータとして GeoJSON シェイプ で構成されます。
クエリ演算子
地理空間データをクエリするには、次のいずれかのクエリ演算子を使用します。
$near$geoWithin$nearSphere$geoIntersects2DSPHERE インデックスが必要です
これらのクエリ演算子は、 Scalaドライバー内で Filtersオブジェクトの near()、geoWithin()、nearSphere()、geoIntersects() メソッドを使用して指定できます。
地理空間クエリ演算子の詳細については、サーバー マニュアルの「地理空間クエリ演算子」ガイドの「地理空間クエリ演算子」セクションを参照してください。
Filtersヘルパーメソッドの完全なリストを表示するには、 フィルターAPIドキュメントを参照してください。
クエリ パラメータ
地理空間クエリで使用する形状を指定するには、 Scalaドライバーの Position、Point、LineString、Polygon クラスを使用します。
GeoJSON シェイプ クラスの詳細については、GeoJSONパッケージ APIドキュメント を参照してください。
地理空間クエリの例
次の例では、 サンプルデータベース内のMongoDB Atlastheaters sample_mflixコレクションを使用します。独自の無料階層 Atlas クラスターを設定する方法と、サンプルデータセットをロードする方法については、 「 Scalaドライバーを使い始める 」ガイドを参照してください。
このセクションの例には、次のインポートが必要です。
import org.mongodb.scala.* import org.mongodb.scala.model.Indexes import org.mongodb.scala.model.Filters import org.mongodb.scala.model.Projections import com.mongodb.client.model.geojson.{Point, Polygon, Position} import java.util.Arrays import java.util.concurrent.TimeUnit import scala.concurrent.Await import scala.concurrent.duration.Duration
theatersコレクションには、 location.geoフィールドの2dsphereインデックスがすでに含まれています。
近接性によるクエリ
点に最も近いドキュメントから最も遠いドキュメントの順に検索して返すには、Filtersオブジェクトの near() メソッドを使用します。 near() メソッドは、$nearクエリ演算子を使用してクエリを構築します。
次の例では、指定された GeoJSON Pointインスタンスから最大 1000 メートル離れたドキュメントを、最も近いものから最も遠いものの順にソートして返します。
val refPoint = new Point(new Position(-73.986805, 40.7620853)) val findObservable = collection.find(Filters.near("location.geo", refPoint, Some(1000.0), Some(0.0))) val results = Await.result(findObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
{"_id": {"$oid": "59a47287cfa9a3a73e51e8e2"}, "theaterId": 1908, "location": {"address": {"street1": "750 Seventh Ave", "city": "New York", "state": "NY", "zipcode": "10019"}, "geo": {"type": "Point", "coordinates": [-73.983487, 40.76078]}}} {"_id": {"$oid": "59a47286cfa9a3a73e51e838"}, "theaterId": 1448, "location": {"address": {"street1": "1880 Broadway", "city": "New York", "state": "NY", "zipcode": "10023"}, "geo": {"type": "Point", "coordinates": [-73.982094, 40.769882]}}}
Tip
MongoDB は、GPS インスタンスと同じ参照システムを使用して、地球上の形状を計算します。
$near 演算子の詳細については、サーバー マニュアルの $near に関する参照を参照してください。
範囲内のクエリ
指定した形状内の地理空間データを検索するには、Filtersオブジェクトの geoWithin() メソッドを使用します。 geoWithin() メソッドは、$geoWithinクエリ演算子を使用してクエリを構築します。
次の例では、Long Expression の セクションで映画館を検索します。この例では、各結果に location.address.cityフィールドのみが含まれ、_idフィールドが除外されるようにプロジェクションを適用します。
val longIslandTriangle = new Polygon(Arrays.asList( new Position(-72.0, 40.0), new Position(-74.0, 41.0), new Position(-72.0, 39.0), new Position(-72.0, 40.0) )) val projection = Projections.fields( Projections.include("location.address.city"), Projections.excludeId() ) val geoWithinComparison = Filters.geoWithin("location.geo", longIslandTriangle) val findObservable = collection.find(geoWithinComparison).projection(projection) val results = Await.result(findObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) results.foreach(doc => println(doc.toJson()))
{"location": {"address": {"city": "Baldwin"}}} {"location": {"address": {"city": "Levittown"}}} {"location": {"address": {"city": "Westbury"}}} {"location": {"address": {"city": "Mount Vernon"}}} {"location": {"address": {"city": "Massapequa"}}}
次の図は、longIslandTriangle 変数によって定義される多角形と、クエリが返す映画館の場所を表すドットを示しています。

$geoWithin 演算子の詳細については、サーバー マニュアルの $geoWithin 参照を参照してください。
詳細情報
地理空間クエリの実行の詳細については、サーバー マニュアルの「地理空間クエリ 」を参照してください。