Para agentes de IA: um índice de documentação está disponível em https://www.mongodb.com/pt-br/docs/llms.txt — as versões de markdown de todas as páginas estão disponíveis anexando .md a qualquer caminho de URL.
Menu Docs

Encontre restaurantes com queries geoespaciais

A indexação geoespacial do MongoDB permite que você execute com eficiência consultas 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 consultas para um aplicativo geoespacial simples.

Este tutorial apresentará brevemente os conceitos de índices geoespaciais e, em seguida, 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 em 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 } } })