Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ /

Encontre restaurantes com queries geoespaciais

Nesta página

  • Visão geral
  • Distorção
  • Procurando restaurantes

A indexação geoespacial do MongoDB permite que você execute com eficiência queries espaciais em uma coleção que contém formas e pontos geoespaciais. Para mostrar os recursos geoespaciais e comparar diferentes abordagens, este tutorial guiará você pelo processo de escrever queries para um aplicativo geoespacial simples.

Este tutorial introduzirá brevemente os conceitos de índices geoespaciais, e então demonstrará seu uso com $geoWithin, $geoIntersects e $nearSphere.

Suponha que você esteja projetando um aplicativo móvel para ajudar os usuários a encontrar restaurantes na cidade de Nova York. O aplicativo deve:

  • Determine a vizinhança atual do usuário usando $geoIntersects,

  • Mostre o número de restaurantes nesse bairro usando $geoWithin e

  • Encontre restaurantes dentro de uma distância especificada do usuário utilizando o $nearSphere.

Este tutorial utilizará um índice 2dsphere para fazer query destes dados em geometria esférica.

Para mais informações sobre geometrias esféricas e planas, consulte Modelos Geoespaciais.

A geometria esférica aparecerá distorcida quando visualizada em um mapa devido à natureza da projeção de uma esfera tridimensional, como a Terra, em uma superfície plana.

Por exemplo, pegue a especificação do quadrado esférico definido pelos pontos de latitude longitude (0,0), (80,0), (80,80) e (0,80). A figura a seguir representa a área abrangida por esta região:

Diagrama de um quadrado projetado em uma esfera.
clique para ampliar

Baixe os conjuntos de dados de exemplo de https://raw.githubusophyllument.com/mongodb/docs-assets/geospatial/neighborhoods.json e https://raw.githubusophyllument.com/mongodb/docs-assets/geospatial/restaurants.json. Eles contêm as coleções restaurants e neighborhoods respectivamente.

Após baixar os conjuntos de dados, importe-os para o banco de dados:

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

Um índice geoespacial e quase sempre melhora o desempenho das consultas $geoWithin e $geoIntersects.

Como esses dados são geográficos, crie um índice 2dsphere em cada coleção usando mongosh:

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

Inspecione uma entrada na coleção recém-criada de restaurants em mongosh:

db.restaurants.findOne()

Esta query retorna um documento como o seguinte:

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

Este documento do restaurante corresponde ao local mostrado na seguinte figura:

Mapa de um único ponto geoespacial.

Como o tutorial utiliza um índice do 2dsphere, os dados de geometria no campo location devem seguir o formato GeoJSON.

Agora inspecione uma entrada na coleção neighborhoods:

db.neighborhoods.findOne()

Esta query retornará um documento como o seguinte:

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

Essa geometria corresponde à região representada na figura a seguir:

Mapa de um polígono geoespacial.
clique para ampliar

Supondo que o dispositivo móvel do usuário possa fornecer uma localização razoavelmente precisa para o usuário, é simples encontrar a vizinhança atual do usuário com $geoIntersects.

Suponha que o usuário esteja localizado a -73.93414657 de longitude e 40.82302903 de latitude. Para localizar a vizinhança atual, você especificará um ponto usando o campo $geometry especial no formato GeoJSON:

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

Esta query retornará o seguinte resultado:

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

Você também pode fazer uma query para encontrar todos os restaurantes contidos em determinado bairro. Execute o seguinte em mongosh para localizar o bairro que contém o usuário e, em seguida, conte os restaurantes dentro desse bairro:

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 dirá que há 127 restaurantes no bairro solicitado, visualizados na seguinte figura:

Mapa de todos os restaurantes em um polígono geospacial.
clique para ampliar

Para encontrar restaurantes a uma distância específica de um ponto, você pode usar $geoWithin com $centerSphere para retornar resultados em ordem não classificada ou $nearSphere com $maxDistance se precisar de resultados classificados por distância.

Para encontrar restaurantes dentro de uma região circular, utilize o $geoWithin com $centerSphere. $centerSphere é uma sintaxe específica do MongoDB para denotar uma região circular especificando o centro e o raio em radianos.

$geoWithin não retorna os documentos em nenhuma ordem específica, portanto, pode mostrar ao usuário os documentos mais distantes primeiro.

A seguir, encontrará todos os restaurantes em um raio de cinco milhas do usuário:

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

O segundo argumento do $centerSphere aceita o raio em radianos, então você deve dividi-lo pelo raio da Terra em milhas. Consulte Converter Distância em Radianos para Operadores Esféricos para obter mais informações sobre a conversão entre unidades de distância.

Você também pode usar $nearSphere e especificar um termo $maxDistance em metros. Isso retornará todos os restaurantes em um raio de oito quilômetros do usuário do mais próximo para o mais distante:

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

Voltar

Consultas geoespaciais