$geoNear(集計)
定義
$geoNear
指定した点に近いものから遠いものの順にドキュメントを出力します。
注意
$geoNear
ステージのプロトタイプ形式は次のとおりです。{ $geoNear: { <geoNear options> } } $geoNear
演算子は、次の$geoNear
オプションを含むドキュメント を受け入れます。次のように、すべての距離を処理ドキュメントの座標系と同じ単位で指定します。フィールドタイプ説明distanceField
string計算された距離を含む出力フィールド。埋め込みドキュメント内のフィールドを指定するには、ドット表記を使用します。distanceMultiplier
数値任意。クエリによって返されるすべての距離に乗じる係数。たとえば、distanceMultiplier
を使用して、球面クエリによって返されるラジアンを地球の半径で乗算してキロメートルに変換します。includeLocs
string任意。距離の計算に使用されるロケーションを識別する出力フィールドを指定します。このオプションは、ロケーション フィールドに複数の場所が含まれているロケーションに便利です。埋め込みドキュメント内のフィールドを指定するには、ドット表記を使用します。key
任意。距離を計算するときに使用する地理空間インデックス フィールドを指定します。
コレクションに複数の
2d
インデックスや複数の2dsphere
インデックスがある場合は、使用するインデックス付きフィールドパスをkey
オプションに指定する必要があります。「使用する地理空間インデックスの指定」で多くの例を紹介しています。複数の
2d
インデックスまたは複数の2dsphere
インデックスがあり、key
を指定しない場合、MongoDB はエラーを返します。key
を指定せず、2d
インデックスが最大で 1 つしかない、もしくは2dsphere
インデックスが 1 つしかない場合、または両方ある場合、MongoDB は使用する2d
インデックスを最初に探します。2d
インデックスが存在しない場合、MongoDB は使用する2dsphere
インデックスを探します。maxDistance
数値任意。 ドキュメントが存在できる中心点からの最大距離。 MongoDBは、中心点から指定した距離内にあるドキュメントに結果を制限します。 バージョン 7.2 以降では、数値に変換される有効な定数式を指定できます。
指定された点が GeoJSON の場合は距離をメートル単位で指定し、指定された点が legacy coordinate pairs の場合はラジアン単位で指定します。
minDistance
数値任意。 ドキュメントが存在できる中心点からの最小距離。 MongoDB は、中心点から指定された距離の外側にあるドキュメントに結果を制限します。 バージョン 7.2 以降では、数値に変換される有効な定数式を指定できます。
GeoJSON データの場合はメートル単位で、legacy coordinate pairs の場合はラジアン単位で距離を指定します。
near
GeoJSON ポイントまたは legacy coordinate pairquery
ドキュメントspherical
ブール値任意。MongoDB が 2 点間の距離を計算する方法を決定します。
true
の場合、MongoDB は$nearSphere
セマンティクスを使用し、球面ジオメトリで距離を計算します。false
の場合、MongoDB は$near
セマンティクスを使用します。2dsphere インデックスには球面ジオメトリ、2d インデックスには平面ジオメトリを使用します。
デフォルト: false。
動作
$geoNear
を使用する場合は、次の点に注意してください。
$geoNear
は、パイプラインの最初のステージとしてのみ使用できます。distanceField
オプションを含める必要があります。distanceField
オプションは、計算された距離を格納するフィールドを指定します。$geoNear
は地理空間インデックスが必要です。コレクションに複数の地理空間インデックスがある場合は、
keys
パラメーターを使用して、計算で使用するフィールドを指定します。地理空間インデックスが 1 つしかない場合は、$geoNear
は暗黙的にインデックス付きフィールドを計算に使用します。
$geoNear
は、デフォルトで 100 ドキュメントの制限はなくなりました。MongoDB 5.1以降では、
near
パラメーターは let オプションとバインドされた let オプションをサポートします。MongoDB 5.3以降では、時系列コレクション内の任意のフィールドで
$geoNear
パイプライン演算子を使用できます。MongoDB 6.0 以降では、時系列コレクション内の任意のフィールドに部分インデックスと 2dsphere インデックスを作成できます。
MongoDB 8.0 以降、
$near
、$nearSphere
、および$geoNear
は、指定された GeoJSON ポイントの型がPoint
であることを検証します。それ以外の入力型はエラーを返します。
例
次のドキュメントを使用してコレクション 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
インデックスを保有しています。次の集計では、$geoNear
を使用して、中心 [ -73.99279 , 40.719296 ]
から最大 2 メートルのロケーションにあり、category
が Parks
に等しいドキュメントを検索します。
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.99279 , 40.719296 ] }, distanceField: "dist.calculated", maxDistance: 2, query: { category: "Parks" }, includeLocs: "dist.location", spherical: true } } ])
集計により次の結果が返されます。
{ "_id" : 8, "name" : "Sara D. Roosevelt Park", "category" : "Parks", "location" : { "type" : "Point", "coordinates" : [ -73.9928, 40.7193 ] }, "dist" : { "calculated" : 0.9539931676365992, "location" : { "type" : "Point", "coordinates" : [ -73.9928, 40.7193 ] } } }
一致するドキュメントには、次の 2 つの新しいフィールドが含まれます。
dist.calculated
フィールド(計算された距離を含む)、およびdist.location
フィールド(計算に使用するロケーションを含む)
最小距離
注意
次の例では、minDistance
オプションを使用して、ドキュメントが存在できる中心点からの最小距離を指定します。次の集計では、ロケーションが中心([ -73.99279 , 40.719296 ]
)から 2 メートル以上離れており、category
が Parks
に等しいすべてのドキュメントが検索されます。
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.99279 , 40.719296 ] }, distanceField: "dist.calculated", minDistance: 2, query: { category: "Parks" }, includeLocs: "dist.location", spherical: true } } ])
オプションを使用した $geoNearlet
この例では、次のことが行われます。
let
オプションは、配列の値である[-73.99279,40.719296]
を変数$pt
に設定するために使用されます。$pt
は、$geoNear
ステージのnear
パラメータにlet
オプションとして指定されています。
db.places.aggregate( [ { "$geoNear": { "near":"$$pt", "distanceField":"distance", "maxDistance":2, "query":{"category":"Parks"}, "includeLocs":"dist.location", "spherical":true } } ], { "let":{ "pt": [ -73.99279, 40.719296 ] } } )
この集計は、次の情報を含むすべてのドキュメントを返します。
let
変数で定義された点から最大 2 m 離れたロケーションcategory
はParks
に等しいです。
{ _id: ObjectId("61715cf9b0c1d171bb498fd7"), name: 'Sara D. Roosevelt Park', location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] }, category: 'Parks', distance: 1.4957325341976439e-7, dist: { location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] } } }, { _id: ObjectId("61715cf9b0c1d171bb498fd6"), name: 'Central Park', location: { type: 'Point', coordinates: [ -73.97, 40.77 ] }, category: 'Parks', distance: 0.0009348548688841822, dist: { location: { type: 'Point', coordinates: [ -73.97, 40.77 ] } } }
Bound オプションを使用した $geoNearlet
let
オプションは、$geoNear クエリで使用できる変数をバインドできます。
この例では、$lookup
は次の変数を使用します。
db.places.aggregate( [ { $lookup: { from: "places", let: { pt: "$location" }, pipeline: [ { $geoNear: { near: "$$pt", distanceField: "distance" } } ], as: "joinedField" } }, { $match: { name: "Sara D. Roosevelt Park" } } ] );
この集計は、次を含むドキュメントを返します。
メインのドキュメントとしての「Sara D. Roosevelt Park」ドキュメント。
距離を計算するための
$pt
変数を使用したサブドキュメントとしての places コレクション内の各ドキュメント。
{ _id: ObjectId("61715cf9b0c1d171bb498fd7"), name: 'Sara D. Roosevelt Park', location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] }, category: 'Parks', joinedField: [ { _id: ObjectId("61715cf9b0c1d171bb498fd7"), name: 'Sara D. Roosevelt Park', location: { type: 'Point', coordinates: [ -73.9928, 40.7193 ] }, category: 'Parks', distance: 0 }, { _id: ObjectId("61715cf9b0c1d171bb498fd6"), name: 'Central Park', location: { type: 'Point', coordinates: [ -73.97, 40.77 ] }, category: 'Parks', distance: 5962.448255234964 }, { _id: ObjectId("61715cfab0c1d171bb498fd8"), name: 'Polo Grounds', location: { type: 'Point', coordinates: [ -73.9375, 40.8303 ] }, category: 'Stadiums', distance: 13206.535424939102 } ] }
使用する地理空間インデックスの指定
location
フィールドに 2dsphere インデックスがあり、legacy
フィールドに 2d インデックスがある places
コレクションを考えてみましょう。
places
コレクションのドキュメントには次のようなものがあります。
{ "_id" : 3, "name" : "Polo Grounds", "location": { "type" : "Point", "coordinates" : [ -73.9375, 40.8303 ] }, "legacy" : [ -73.9375, 40.8303 ], "category" : "Stadiums" }
次の例では、key
オプションを使用して、集計で $geoNear
操作に legacy
フィールド値ではなく location
フィールド値を使用する指定にしています。また、パイプラインは $limit
を使用して最大 5 のドキュメントを返します。
注意
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.98142 , 40.71782 ] }, key: "location", distanceField: "dist.calculated", query: { "category": "Parks" } } }, { $limit: 5 } ])
集計により次の結果が返されます。
{ "_id" : 8, "name" : "Sara D. Roosevelt Park", "location" : { "type" : "Point", "coordinates" : [ -73.9928, 40.7193 ] }, "category" : "Parks", "dist" : { "calculated" : 974.175764916902 } } { "_id" : 1, "name" : "Central Park", "location" : { "type" : "Point", "coordinates" : [ -73.97, 40.77 ] }, "legacy" : [ -73.97, 40.77 ], "category" : "Parks", "dist" : { "calculated" : 5887.92792958097 } }