定义
$geoNear按距离指定点最近到最远的顺序输出文档。
注意
$geoNear阶段具有以下原型形式:{ $geoNear: { <geoNear options> } } $geoNear运算符接受包含以下$geoNear选项的文档。使用与已处理文档坐标系相同的单位指定所有距离:字段类型说明distanceField字符串
包含计算出的距离的输出字段。要在嵌入式文档中指定字段,请使用点符号。
distanceMultiplier数字
可选。用于与查询返回的所有距离相乘的系数。例如,使用
distanceMultiplier乘以地球半径,将球形查询返回的弧度转换为公里。includeLocs字符串
可选。这指定了一个输出字段,用于标识用来计算距离的位置。该选项适合位置字段包含多个位置的情况。要在嵌入式文档中指定字段,请使用点符号。
keymaxDistance数字
minDistance数字
可选。文档可与中心点相距的最小距离。MongoDB 会将结果限制为相距中心点指定距离之外的文档。
对于 GeoJSON 数据,以米为单位指定距离;对于传统坐标对,以弧度为单位指定距离。
nearGeoJSON 点或传统坐标对
query文档
spherical布尔
行为
距离计算
$geoNear 根据输入文档周边的最近点计算距离。
示例,如果输入文档是一个形状,$geoNear 则会标识形状周长上距离指定点最近的点,并输出指定点与形状最近点之间的距离。
Considerations
在使用 $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 来指定文档可与中心点相距的最小距离。以下聚合查找距离中心 [ -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 米的位置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 ] } } }
带有绑定 选项的 $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变量将地点集合中的每个文档作为子文档来计算距离。
{ _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 字段值来执行 $geoNear 操作,而不是使用 legacy 字段值。该管道还使用了 $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 } }
本页上的C#示例使用Atlas示例数据集中的 sample_mflix.theaters集合。要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅MongoDB .NET/ C#驱动程序文档中的入门。
以下 Theater、Location 和 Address 类将为 sample_mflix.theaters 集合中的文档建模:
public class Theater { public ObjectId Id { get; set; } [] public int TheaterId { get; set; } [] public Location Location { get; set; } [] public double? Distance { get; set; } } public class Location { [] public Address Address { get; set; } [] public GeoJsonPoint<GeoJson2DGeographicCoordinates> Geo { get; set; } } [] public class Address { [] public string City { get; set; } [] public string State { get; set; } }
要使用 MongoDB .NET/C# 驱动程序将$geoNear 阶段添加到聚合管道,请对 PipelineDefinition 对象调用 GeoNear() 方法。
此方法仅在MongoDB .NET/ C#驾驶员v3.4 及更高版本中可用。
最大距离
以下示例创建一个管道阶段,该阶段返回位于指定点 8000 米半径范围内的文档,并按距离从近到远的顺序排列。该代码包含一个 Query 参数,仅匹配 location.address.state 字段的值为 "NJ" 的文档。代码还会将计算出的距离存储在输出文档的 distance 字段中。
var pipeline = new EmptyPipelineDefinition<Theater>() .GeoNear( GeoJson.Point(GeoJson.Geographic(-74.1, 40.95)), new GeoNearOptions<Theater, Theater> { DistanceField = "distance", MaxDistance = 8000, Key = "location.geo", Query = Builders<Theater>.Filter.Eq(t => t.Location.Address.State, "NJ"), });
最小距离
以下示例按距离升序返回指定点8000 米半径之外的前 4 个匹配文档。该代码包含一个 Query 参数,该参数仅匹配 location.address.state字段值为 "NJ" 的文档。该代码还会将计算出的距离存储在输出文档的 distance字段中。
var pipeline = new EmptyPipelineDefinition<Theater>() .GeoNear( GeoJson.Point(GeoJson.Geographic(-74.1, 40.95)), new GeoNearOptions<Theater, Theater> { DistanceField = "distance", MinDistance = 8000, Key = "location.geo", Query = Builders<Theater>.Filter.Eq(t => t.Location.Address.State, "NJ"), }) .Limit(4);
本页上的 Node.js 示例使用Atlas示例数据集中的 sample_mflix数据库。要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅MongoDB Node.js驾驶员文档中的入门。
要使用MongoDB Node.js驾驶员将 $geoNear 阶段添加到聚合管道,请在管道对象中使用 $geoNear操作符。
最大距离
以下示例创建了一个管道阶段,该阶段按距离升序返回指定点半径 8000 米内的文档。该代码包含一个 query字段,该字段仅匹配 location.address.state字段值为 "NJ" 的文档。该代码还会将计算出的距离存储在输出文档的 distance字段中。然后,该示例运行聚合管道:
const pipeline = [ { $geoNear: { near: { type: "Point", coordinates: [-74.1, 40.95] }, distanceField: "distance", maxDistance: 8000, query: { "location.address.state": "NJ" }, spherical: true } } ]; const cursor = collection.aggregate(pipeline); return cursor;
最小距离
以下示例按距离升序返回指定点8000 米半径之外的前 4 个匹配文档。该代码包含一个 query字段,该字段仅匹配 location.address.state字段值为 "NJ" 的文档。此代码还会将计算出的距离存储在输出文档的 distance字段中:
const pipeline = [ { $geoNear: { near: { type: "Point", coordinates: [-74.1, 40.95] }, distanceField: "distance", minDistance: 8000, query: { "location.address.state": "NJ" }, spherical: true }, }, { $limit: 4 } ]; const cursor = collection.aggregate(pipeline); return cursor;
了解详情
要学习;了解有关相关管道阶段的更多信息,请参阅 $limit 指南。