Definición
$geoNearEmite documentos en orden de más cercano a más lejano desde un punto especificado.
La etapa
$geoNeartiene el siguiente formato de prototipo:{ $geoNear: { <geoNear options> } } El operador
$geoNearacepta un documento que contiene las siguientes opciones$geoNear. Especifica todas las distancias en las mismas unidades que el sistema de coordenadas de los documentos procesados:CampoTipoDescripcióndistanceFieldstring
El campo de salida que contiene la distancia calculada. Para especificar un campo dentro de un documento incrustado, utiliza notación de puntos.
Este campo es obligatorio para consultas en colecciones de series temporales. A partir de MongoDB 8.1,
distanceFieldes opcional para las búsquedas en colecciones que no son de serie de tiempo.distanceMultiplierNúmero
Opcional. Factor para multiplicar todas las distancias devueltas por la query. Por ejemplo, usar el
distanceMultiplierpara convertir radianes, tal como los devuelve una query esférica, a kilómetros multiplicando por el radio de la Tierra.includeLocsstring
opcional. Esto especifica el campo de salida que identifica la ubicación utilizada para calcular la distancia. Esta opción es útil cuando un campo de ubicación contiene varias ubicaciones. Para especificar un campo dentro de un documento incrustado, usa la notación de puntos.
keyOpcional. Especificar el campo geoespacial indexado que se utilizará al calcular la distancia.
Si tu colección tiene varios índices de
2dy/o varios de2dsphere, debes usar la opciónkeypara especificar la ruta de campo indexado que se utilizará. Especificar Qué Índice Geoespacial Usar proporciona un ejemplo completo.Si hay más de un índice
2do más de un índice2dspherey no se especifica unkey, MongoDB devolverá un error.Si no especificas el
key, y tienes como máximo solo un índice2dy/o solo un índice2dsphere, MongoDB primero buscará un índice2dpara usar. Si un índice2dno existe, MongoDB busca un índice2dspherepara usar.Debe especificar el campo
keypara$geoNearen una colección de series de tiempo.maxDistanceNúmero
opcional. La distancia máxima desde el punto central a la que los documentos pueden estar. MongoDB limita los resultados a los documentos que se encuentran dentro de la distancia especificada desde el punto central. A partir de la versión 7.2, puedes especificar una expresión de constante válida que se resuelva en un número.
Especifica la distancia en metros si el punto especificado es GeoJSON y en radianes si el punto especificado es legacy coordinate pairs.
minDistanceNúmero
opcional. La distancia mínima desde el punto central a la que los documentos pueden estar. MongoDB limita los resultados a aquellos documentos que caen fuera de la distancia especificada desde el punto central. A partir de la versión 7.2, puedes especificar una expresión constante válida que se resuelva en un número.
Especifica la distancia en metros para los datos GeoJSON y en radianes para los legacy coordinate pairs.
nearPunto GeoJSON o par de coordenadas antiguo
queryDocumento
opcional. Limita los resultados a los documentos que coinciden con la query. La sintaxis de queries es la sintaxis habitual de query para operaciones de lectura en MongoDB.
No puedes especificar un predicado
$nearen el campoqueryde la etapa$geoNear.No se puede usar el campo
querypara$geoNearen una colección de series de tiempo.sphericalbooleano
Opcional. Determina cómo MongoDB calcula la distancia entre dos puntos:
Cuando
true, MongoDB utiliza la semántica$nearSpherey calcula las distancias utilizando geometría esférica.Al
false, MongoDB utiliza la$nearsemántica: geometría esférica para los índices 2dsphere e índices planares para los índices 2d.
Por defecto: falso.
Comportamiento
Cálculos de distancia
$geoNear calcula la distancia basándose en el punto más cercano del perímetro del documento de entrada.
Por ejemplo, si el documento de entrada es una forma, $geoNear identifica el punto en el perímetro de la forma que está más cerca del punto especificado y muestra la distancia entre el punto especificado y el punto más cercano de la forma.
Considerations
Al utilizar $geoNear, tenga en cuenta que:
Solo se puede utilizar
$geoNearcomo la primera etapa de un pipeline.$geoNearrequiere un índice geoespacial.Si tienes más de un índice geoespacial en la colección, usa el parámetro
keyspara especificar qué campo se debe usar en el cálculo. Si sólo tiene un índice geoespacial,$geoNearutiliza implícitamente el campo indexado para el cálculo.
No puedes especificar un predicado
$nearen el campoqueryde la etapa$geoNear.$geoNearya no tiene un límite por defecto de 100 documentos.El parámetro
nearadmite la opción let y la opción let atada.Puede utilizar el operador de pipeline
$geoNearen cualquier campo de una colección de series de tiempo. Sin embargo, no puedes utilizar el campoquerypara$geoNearen una colección de series de tiempo.Puede crear índices parciales e 2dsphere en cualquier campo de una colección de series de tiempo.
A partir de MongoDB 8.0,
$near,$nearSpherey$geoNearvalidan que el tipo de los puntos GeoJSON especificados seaPoint. Cualquier otro tipo de entrada genera un error.
Ejemplos
Cree una colección places con los siguientes documentos:
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" } ] )
La siguiente operación crea un índice 2dsphere en el campo location:
db.places.createIndex( { location: "2dsphere" } )
Distancia máxima
La colección places mencionada anteriormente tiene un índice 2dsphere. La siguiente agregación utiliza $geoNear para encontrar documentos con una ubicación a lo más 2 metros del centro [ -73.99279 , 40.719296 ] y category igual a 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 } } ])
La agregación devuelve lo siguiente:
{ "_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 ] } } }
El documento coincidente contiene dos nuevos campos:
dist.calculatedcampo que contiene la distancia calculada, ydist.locationcampo que contiene la ubicación utilizada en el cálculo
Distancia mínima
El siguiente ejemplo utiliza la opción minDistance para especificar la distancia mínima desde el punto central a la que pueden estar los documentos. La siguiente agregación encuentra todos los documentos con una ubicación al menos a 2 metros del centro [ -73.99279 , 40.719296 ] y category igual a 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 con la opción let
En este ejemplo:
La opción
letse utiliza para establecer un valor de arreglo de[-73.99279,40.719296]a la variable$pt.$ptse especifica como una opciónletpara el parámetronearen la etapa$geoNear.
db.places.aggregate( [ { "$geoNear": { "near":"$$pt", "distanceField":"distance", "maxDistance":2, "query":{"category":"Parks"}, "includeLocs":"dist.location", "spherical":true } } ], { "let":{ "pt": [ -73.99279, 40.719296 ] } } )
La agregación retorna todos los documentos con:
Una ubicación a no más de 2 metros del punto definido en la variable
letUn
categoryigual aParks.
{ _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 con opción Bound let
La opción let puede vincular una variable que se puede utilizar en una query $geoNear.
En este ejemplo, $lookup utiliza:
letpara definir$pt.$geoNearenpipeline.$ptpara definirnearen la etapa de pipeline$geoNear.
db.places.aggregate( [ { $lookup: { from: "places", let: { pt: "$location" }, pipeline: [ { $geoNear: { near: "$$pt", distanceField: "distance" } } ], as: "joinedField" } }, { $match: { name: "Sara D. Roosevelt Park" } } ] );
La agregación devuelve un documento con:
El documento de 'Sara D. Roosevelt Park' como el documento principal.
Cada documento en la colección de lugares como subdocumentos que utilizan la variable
$ptpara calcular la distancia.
{ _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 } ] }
Especifique qué índice geoespacial utilizar
Considerar una colección places que tiene un índice 2dsphere en el campo location y un índice 2D en el campo legacy.
Un documento en la colección places es similar a lo siguiente:
{ "_id" : 3, "name" : "Polo Grounds", "location": { "type" : "Point", "coordinates" : [ -73.9375, 40.8303 ] }, "legacy" : [ -73.9375, 40.8303 ], "category" : "Stadiums" }
El siguiente ejemplo utiliza la opción key para especificar que la agregación debe utilizar los valores del campo location para la operación $geoNear en lugar de los valores del campo legacy. El pipeline también utiliza $limit para devolver como máximo 5 documentos.
db.places.aggregate([ { $geoNear: { near: { type: "Point", coordinates: [ -73.98142 , 40.71782 ] }, key: "location", distanceField: "dist.calculated", query: { "category": "Parks" } } }, { $limit: 5 } ])
La agregación devuelve lo siguiente:
{ "_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 } }
Los ejemplos de C# en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulta Primeros pasos en la documentación del controlador de MongoDB .NET/C#.
Las siguientes clases Theater, TheaterLocation, y TheaterAddress modelan los documentos de la colección sample_mflix.theaters:
[] public class Theater { [] public ObjectId Id { get; set; } [] public int TheaterId { get; set; } [] public TheaterLocation Location { get; set; } = null!; [] public double? Distance { get; set; } } [] public class TheaterLocation { [] public TheaterAddress Address { get; set; } = null!; } [] public class TheaterAddress { [] public string? City { get; set; } [] public string? State { get; set; } }
Para usar el driver de MongoDB .NET/C# para añadir una etapa $geoNear a un pipeline de agregación, llamar a la GeoNear() método en un objeto PipelineDefinition.
Este método está disponible solo en MongoDB .NET/controlador de C# v3.4 y versiones posteriores.
Distancia máxima
El siguiente ejemplo crea una etapa de pipeline que devuelve documentos en un radio de 8000 metros del punto especificado, en orden de distancia ascendente. El código incluye un parámetro Query que solo coincide con documentos en los que el valor del campo location.address.state es "NJ". El código también almacena la distancia calculada en el campo distance de los documentos de salida.
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"), });
{ "_id" : "...", "theaterId" : 344, "location" : { "address" : { "city" : "Paramus", "state" : "NJ" } }, "distance" : "..." } { "_id" : "...", "theaterId" : 2978, "location" : { "address" : { "city" : "Paramus", "state" : "NJ" } }, "distance" : "..." } { "_id" : "...", "theaterId" : 1936, "location" : { "address" : { "city" : "Paramus", "state" : "NJ" } }, "distance" : "..." } { "_id" : "...", "theaterId" : 887, "location" : { "address" : { "city" : "Paramus", "state" : "NJ" } }, "distance" : "..." }
Distancia mínima
El siguiente ejemplo devuelve los primeros 4 documentos coincidentes fuera de un radio de 8000 metros del punto especificado, en orden ascendente de distancia. El código incluye un parámetro Query que solo coincide con documentos en los que el valor del campo location.address.state es "NJ". El código también almacena la distancia calculada en el campo distance de los documentos de salida.
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);
{ "_id" : "...", "theaterId" : 468, "location" : { "address" : { "city" : "Woodland Park", "state" : "NJ" } }, "distance" : "..." } { "_id" : "...", "theaterId" : 8539, "location" : { "address" : { "city" : "Bloomfield", "state" : "NJ" } }, "distance" : "..." } { "_id" : "...", "theaterId" : 2703, "location" : { "address" : { "city" : "Wayne", "state" : "NJ" } }, "distance" : "..." } { "_id" : "...", "theaterId" : 2509, "location" : { "address" : { "city" : "Riverdale", "state" : "NJ" } }, "distance" : "..." }
Los ejemplos de Node.js en esta página utilizan la base de datos sample_mflix de los conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte Primeros pasos en la documentación del controlador de MongoDB Node.js.
Para utilizar el controlador de MongoDB Node.js para agregar una etapa de $geoNear a una canalización de agregación, utilice el Operador $geoNear en un objeto de canalización.
Distancia máxima
El siguiente ejemplo crea una etapa de pipeline que devuelve documentos en un radio de 8000 metros del punto especificado, en orden de distancia ascendente. El código incluye un campo query que solo coincide con los documentos donde el valor del campo location.address.state es "NJ". El código también almacena la distancia calculada en el campo distance de los documentos de salida. El ejemplo ejecuta entonces el pipeline de agregación:
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;
Distancia mínima
El siguiente ejemplo devuelve los primeros 4 documentos coincidentes fuera de un radio de 8000 metros del punto especificado, en orden de distancia ascendente. El código incluye un campo query que solo coincide con los documentos donde el valor del campo location.address.state es "NJ". El código también almacena la distancia calculada en el campo distance de los documentos de salida:
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;
Obtén más información
Para aprender más sobre las etapas relacionadas del pipeline, consulta la guía $limit.