$geoNear (聚合)
定义
$geoNear
按照从指定点最近到最远的顺序输出文档。
$geoNear
阶段的{ $geoNear: { <geoNear options> } } 操作符
$geoNear
接受一个包含以下 文档 的选项。所有距离均需与处理文档的坐标系单位相同。字段类型描述distanceField
字符串包含计算出的距离的输出字段。要指定嵌套文档中的字段,请使用 点表示法。distanceMultiplier
数字可选。用于乘以查询返回的所有距离的系数。例如,可以使用distanceMultiplier
将球面查询返回的弧度转换为千米,通过乘以地球半径来实现。includeLocs
字符串可选。指定用于计算距离的输出字段。当位置字段包含多个位置时,此选项很有用。要指定嵌套文档中的字段,请使用 点表示法。key
可选。指定在计算距离时使用的地理空间索引字段。
如果你的集合具有多个
2d
和/或多个2dsphere
索引,你必须使用key
选项来指定要使用的索引字段路径。指定要使用的地理空间索引 提供了完整示例。如果有多个
2d
索引或多个2dsphere
索引,并且你没有指定key
,MongoDB 将返回一个错误。如果没有指定
key
,并且你只有一个2d
索引和/或只有一个2dsphere
索引,MongoDB 首先寻找一个2d
索引来使用。如果没有2d
索引,MongoDB 将寻找一个2dsphere
索引来使用。maxDistance
数字minDistance
数字可选。文档可以从中心点达到的最小距离。MongoDB 限制结果仅限于位于指定距离外的文档。从版本 7.2 开始,你可以指定一个有效的常量 表达式,它解析为一个数字。
对于 GeoJSON 数据,请以米为单位指定距离;对于旧坐标对,请以弧度为单位指定距离。
near
GeoJSON 点或 旧坐标对查询
文档球面
布尔值
行为
距离计算
$geoNear
基于输入文档的边界上最近点来计算距离。
例如,如果输入文档是一个形状,$geoNear
会识别形状周界上距离指定点最近的那一点,并输出指定点和形状最近点的距离。
注意事项
当使用 $geoNear
时,请考虑以下因素:
示例
创建一个包含以下文档的集合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 ] } } }
匹配的文档包含两个新字段
dist.calculated
字段,包含计算出的距离,以及dist.location
字段,包含用于计算的地点。
最小距离
以下示例使用选项 minDistance
来指定文档可以位于中心点多少距离以内。以下聚合查找所有至少距离中心点2米远的文档 [ -73.99279 , 40.719296 ]
且 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 } } ])
$geoNear 与 let
选项
在此示例中
使用
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米范围内的位置类别等于
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 ] } } }
$geoNear 与边界 let
选项
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 } ] }
指定使用哪种地理空间索引
假设有一个 places
集合,它有一个在 location
字段上的 2dsphere 索引,以及在 legacy
字段上的 2d 索引。
places 集合中的文档如下所示:
{ "_id" : 3, "name" : "Polo Grounds", "location": { "type" : "Point", "coordinates" : [ -73.9375, 40.8303 ] }, "legacy" : [ -73.9375, 40.8303 ], "category" : "Stadiums" }
以下示例使用 key
选项指定聚合应使用 location
字段值而不是 legacy
字段值进行 $geoNear
操作。管道还使用 $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 } }