close
Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /

Encuentre restaurantes con consultas geoespaciales

MongoDB's El indexación geoespacial permite ejecutar queries espaciales de manera eficiente en una colección que contiene formas y puntos geoespaciales. Para mostrar las capacidades de las funcionalidades geoespaciales y comparar diferentes enfoques, este tutorial te guiará a través del proceso de escribir queries para una aplicación geoespacial sencilla.

Este tutorial presentará brevemente los conceptos de los índices geoespaciales y, a continuación, demostrará su uso con $geoWithin, $geoIntersects y $nearSphere.

Supón que estás diseñando una aplicación móvil para ayudar a los usuarios a encontrar restaurantes en la ciudad de Nueva York. La aplicación debe:

  • Determina el vecindario actual del usuario usando $geoIntersects,

  • Muestra el número de restaurantes en ese barrio utilizando $geoWithin, y

  • Encuentra restaurantes dentro de una distancia especificada del usuario utilizando $nearSphere.

Este tutorial utilizará un índice 2dsphere para query estos datos sobre geometría esférica.

Para obtener más información sobre geometrías esféricas y planas, consulte Modelos geoespaciales.

La geometría esférica parecerá distorsionada cuando se visualiza en un mapa debido a la naturaleza de proyectar una esfera tridimensional, como la tierra, sobre un plano plano.

Por ejemplo, toma la especificación del cuadrado esférico definido por los puntos de longitud y latitud (0,0), (80,0), (80,80) y (0,80). La siguiente figura muestra el área cubierta por esta región:

Diagrama de un cuadrado proyectado sobre una esfera.
haga clic para ampliar

Descargue los conjuntos de datos de ejemplo desde https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/neighborhoods.json y https://raw.githubusercontent.com/mongodb/docs-assets/geospatial/restaurants.json. Estos contienen las colecciones restaurants y neighborhoods respectivamente.

Después de descargar los conjuntos de datos, impórtalos en la base de datos:

mongoimport <path to restaurants.json> -c=restaurants
mongoimport <path to neighborhoods.json> -c=neighborhoods

Un índice geoespacial, y casi siempre mejora el rendimiento de $geoWithin y $geoIntersects consultas.

Como estos datos son geográficos, crea un índice 2dsphere en cada colección utilizando mongosh:

db.restaurants.createIndex({ location: "2dsphere" })
db.neighborhoods.createIndex({ geometry: "2dsphere" })

Inspecciona una entrada en la nueva colección restaurants en mongosh:

db.restaurants.findOne()

Esta query devuelve un documento como el siguiente:

{
location: {
type: "Point",
coordinates: [-73.856077, 40.848447]
},
name: "Morris Park Bake Shop"
}

Este documento de restaurante corresponde a la ubicación que se muestra en la siguiente figura:

Mapa de un único punto geoespacial.

Debido a que el tutorial utiliza un índice 2dsphere, los datos de geometría en el campo location deben cumplir con el formato GeoJSON.

Ahora inspeccione una entrada en la colección neighborhoods:

db.neighborhoods.findOne()

Esta query devolverá un documento similar al siguiente:

{
geometry: {
type: "Polygon",
coordinates: [[
[ -73.99, 40.75 ],
...
[ -73.98, 40.76 ],
[ -73.99, 40.75 ]
]]
},
name: "Hell's Kitchen"
}

Esta geometría corresponde a la región representada en la siguiente figura:

Mapa de un polígono geoespacial.
haga clic para ampliar

Suponiendo que el dispositivo móvil del usuario pueda proporcionar una ubicación razonablemente precisa para el usuario, es sencillo encontrar el vecindario actual del usuario con $geoIntersects.

Supón que el usuario se encuentra en la longitud -73.93414657 y latitud 40.82302903. Para encontrar el vecindario actual, deberás especificar un punto utilizando el campo especial $geometry en formato GeoJSON:

db.neighborhoods.findOne({ geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } })

Esta consulta devolverá el siguiente resultado:

{
"_id" : ObjectId("55cb9c666c522cafdb053a68"),
"geometry" : {
"type" : "Polygon",
"coordinates" : [
[
[
-73.93383000695911,
40.81949109558767
],
...
]
]
},
"name" : "Central Harlem North-Polo Grounds"
}

También puedes hacer una query para encontrar todos los restaurantes en un barrio determinado. Ejecute lo siguiente en mongosh para encontrar el vecindario que contenga al usuario y luego cuente los restaurantes dentro de ese vecindario:

var neighborhood = db.neighborhoods.findOne( { geometry: { $geoIntersects: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] } } } } )
db.restaurants.find( { location: { $geoWithin: { $geometry: neighborhood.geometry } } } ).count()

Esta query te indicará que hay 127 restaurantes en el vecindario solicitado, visualizados en la siguiente figura:

Mapa de todos los restaurantes en un polígono geoespacial.
haga clic para ampliar

Para encontrar restaurantes dentro de una distancia específica de un punto, puedes usar $geoWithin con $centerSphere para devolver resultados en un orden no ordenado, o $nearSphere con $maxDistance si necesitas resultados ordenados por distancia.

Para encontrar restaurantes dentro de una región circular, utiliza $geoWithin con $centerSphere. $centerSphere es una sintaxis específica de MongoDB para denotar una región circular especificando el centro y el radio en radianes.

$geoWithin no devuelve los documentos en un orden específico, por lo que puede mostrarle al usuario primero los documentos más lejanos.

Lo siguiente encontrará todos los restaurantes dentro de cinco millas del usuario:

db.restaurants.find({ location:
{ $geoWithin:
{ $centerSphere: [ [ -73.93414657, 40.82302903 ], 5 / 3963.2 ] } } })

$centerSphere El segundo argumento acepta el radio en radianes, por lo que debes dividirlo por el radio de la tierra en millas. Consulta Convertir distancia a radianes con operadores esféricos para obtener más información sobre la conversión entre unidades de distancia.

También puede usar $nearSphere y especificar un término de $maxDistance en metros. Esto devolverá todos los restaurantes dentro de cinco millas del usuario en orden ordenado desde el más cercano al más lejano:

var METERS_PER_MILE = 1609.34
db.restaurants.find({ location: { $nearSphere: { $geometry: { type: "Point", coordinates: [ -73.93414657, 40.82302903 ] }, $maxDistance: 5 * METERS_PER_MILE } } })

Volver

Query geoespacial

En esta página