Pesquisar geoespacialmente
Nesta página
Visão geral
Neste guia, você pode aprender como pesquisar dados geoespaciais com o MongoDB Kotlin Driver e os diferentes formatos de dados geoespaciais suportados pelo MongoDB.
Dados geoespaciais são dados que representam uma localização geográfica na superfície da Terra. Exemplos de dados geoespaciais incluem:
Localizações de cinemas
Fronteiras de países
Rotas de passeios de bicicleta
Áreas de exercícios para cães na cidade de Nova York
Coordenadas na Terra
Para armazenar e fazer query dos seus dados geoespaciais no MongoDB, utilize GeoJSON. GeoJSON é um formato de dados criado pela Internet Engineering Task Force (IETF).
Aqui está a localização da sede do MongoDB no GeoJSON:
"MongoDB Headquarters" : { "type": "point", "coordinates": [-73.986805, 40.7620853] }
Para obter informações sólidas sobre o GeoJSON,consulte a especificação oficial do IETF .
Posições GeoJSON
Uma posição representa um único local na Terra e existe em código como uma array contendo dois ou três valores numéricos:
Longitude na primeira posição (obrigatório)
Latitude na segunda posição (obrigatório)
Elevação na terceira posição (opcional)
Importante
Longitude e depois latitude
A GeoJSON ordena coordenadas como longitude primeiro e latitude segundo. Isto pode ser surpreendente como convenções do sistema de coordenadas geográficas geralmente listam latitude primeiro e longitude segundo. Certifique-se de verificar qual formato qualquer outra ferramenta com a qual você está trabalhando usa. Ferramentas populares como OpenStreetMap e Google Maps listam coordenadas como latitude primeiro e longitude segundo.
Tipos de GeoJSON
O tipo de objeto GeoJSON determina sua forma geométrica. Formas geométricas são compostas por posições.
Aqui estão alguns tipos de GeoJSON comuns e como você pode especificá-los com posições:
Point
: uma única posição. Isso pode representar a localização de uma construção.LineString
: uma matriz de duas ou mais posições, formando assim uma série de segmentos de linha. Isso pode representar a rota da Grande Muralha da China.Polygon
: uma array de posições em que a primeira e a última posição são iguais, contendo algum espaço. Isso pode representar o território dentro da Cidade do Vaticano.
Para saber mais sobre as formas que você pode usar no MongoDB, consulte a entrada do manual GeoJSON.
Index
Para query dados armazenados no formato GeoJSON, adicione o campo que contém dados GeoJSON a um índice do 2dsphere
. O seguinte trecho cria um índice 2dsphere
no campo location.geo
utilizando o construtor Indexes
:
collection.createIndex((Indexes.geo2dsphere("location.geo")))
Para obter mais informações sobre o construtor Indexes
, consulte nosso guia sobre o construtor de índices.
Coordenadas em um plano 2D
Você pode armazenar dados geoespaciais utilizando coordenadas do x
e y
em um plano Euclidiano bidimensional. Nos referimos a coordenadas em um plano bidimensional como "legacy coordinate pairs".
Os legacy coordinate pairs têm a seguinte estrutura:
"<field name>" : [ x, y ]
Seu campo deve conter uma array de dois valores em que o primeiro representa o valor do eixo x
e o segundo representa o valor do eixo y
.
Index
Para query dados armazenados como legacy coordinate pairs, você deve adicionar o campo que contém legacy coordinate pairs a um índice 2d
. O seguinte trecho cria um índice 2d
no campo coordinates
utilizando o construtor Indexes
:
collection.createIndex((Indexes.geo2d("coordinates")))
Para obter mais informações sobre o construtor Indexes
, consulte nosso guia sobre o construtor de índices.
Para mais informações sobre legacy coordinate pairs, consulte a página manual do servidor MongoDB sobre legacy coordinate pairs.
Dica
Operadores suportados
Os índices esféricos (2dsphere
) e planos (2d
) suportam alguns, mas não todos, dos mesmos operadores de query. Para uma lista completa de operadores e sua compatibilidade de índice, consulte a entrada manual para queries geoespaciais.
Consultas geoespaciais
As queries geoespaciais consistem em um operador de query e formas GeoJSON como parâmetros de query.
Operadores de Consulta
Para fazer query de seus dados geoespaciais, utilize um dos seguintes operadores de query:
$near
$geoWithin
$nearSphere
$geoIntersects
requer um índice de 2dsphere
Você pode especificar esses operadores de query no driver MongoDB Kotlin com os métodos utilitários near()
, geoWithin()
, nearSphere()
e geoIntersects()
da classe de construtor Filters
.
Para mais informações sobre operadores de query geoespacial, consulte a entrada manual para queries geoespaciais.
Para obter mais informações sobre Filters
, consulte nosso guia sobre o construtor de filtros.
parâmetros de query
Para especificar uma forma para utilizar em uma query geoespacial, utilize as classes Position
, Point
, LineString
e Polygon
do driver MongoDB Kotlin.
Para obter uma lista completa das formas GeoJSON disponíveis no driver Kotlin do MongoDB, consulte o pacote GeoJSON Documentação da API.
Exemplos
Os exemplos seguintes utilizam o conjunto de dados de amostra do MongoDB Atlas. Você pode aprender como definir seu próprio Atlas cluster de camada grátis e como carregar o conjunto de dados de exemplo em nosso guia de início rápido.
Os exemplos utilizam a coleção do theaters
no banco de dados do sample_mflix
a partir do conjunto de dados de amostra.
Os exemplos exigem as seguintes importações:
import com.mongodb.client.model.geojson.Point import com.mongodb.client.model.geojson.Polygon import com.mongodb.client.model.geojson.Position import com.mongodb.client.model.Filters.near import com.mongodb.client.model.Filters.geoWithin import com.mongodb.client.model.Projections.fields import com.mongodb.client.model.Projections.include import com.mongodb.client.model.Projections.excludeId
Os dados são modelados usando a seguinte classe de dados Kotlin:
data class Theater( val theaterId: Int, val location: Location ) { data class Location( val address: Address, val geo: Point ) { data class Address( val street1: String, val street2: String? = null, val city: String, val state: String, val zipcode: String ) } }
Os resultados são modelados usando a seguinte classe de dados Kotlin:
data class TheaterResults( val location: Location ) { data class Location( val address: Address ) { data class Address( val city: String ) } }
A collection theaters
já contém um índice 2dsphere
no campo "${Theater::location.name}.${Theater.Location::geo.name}"
.
Query por proximidade
Para pesquisar e retornar documento do mais próximo para o mais distante de um ponto, use o método de utilidade estática near()
da classe de construtor Filters
. O método near()
constrói uma query com o operador de query $near
.
O exemplo a seguir faz uma query para os cinemas entre 10,000
e 5,000
metros do Grande Gramado do Central Parque:
val database = client.getDatabase("sample_mflix") val collection = database.getCollection<TheaterResults>("theaters") val centralPark = Point(Position(-73.9667, 40.78)) val query = Filters.near( "${Theater::location.name}.${Theater.Location::geo.name}", centralPark, 10000.0, 5000.0 ) val projection = Projections.fields( Projections.include( "${Theater::location.name}.${Theater.Location::address.name}.${Theater.Location.Address::city.name}"), Projections.excludeId() ) val resultsFlow = collection.find(query).projection(projection) resultsFlow.collect { println(it) }
TheaterResults(location=Location(address=Address(city=Bronx))) TheaterResults(location=Location(address=Address(city=New York))) TheaterResults(location=Location(address=Address(city=New York))) TheaterResults(location=Location(address=Address(city=Long Island City))) TheaterResults(location=Location(address=Address(city=New York))) TheaterResults(location=Location(address=Address(city=Secaucus))) TheaterResults(location=Location(address=Address(city=Jersey City))) TheaterResults(location=Location(address=Address(city=Elmhurst))) TheaterResults(location=Location(address=Address(city=Flushing))) TheaterResults(location=Location(address=Address(city=Flushing))) TheaterResults(location=Location(address=Address(city=Flushing))) TheaterResults(location=Location(address=Address(city=Elmhurst)))
Dica
Curiosidade
O MongoDB utiliza o mesmo sistema de referência que os Satélites gps para calcular geometrias sobre a Terra.
Para obter mais informações sobre o operador $near
, consulte a documentação de referência de $near.
Para obter mais informações sobre Filters
, consulte nosso guia sobre o construtor de filtros.
Query dentro de um intervalo
Para pesquisar dados geoespaciais dentro de uma forma especificada, utilize o método de utilidade estática geoWithin()
da classe de construtor Filters
. O método geoWithin()
constrói uma query com o operador de query $geoWithin
.
O exemplo a seguir pesquisar cinemas em uma seção de Long Console.
val longIslandTriangle = Polygon( listOf( Position(-72.0, 40.0), Position(-74.0, 41.0), Position(-72.0, 39.0), Position(-72.0, 40.0) ) ) val projection = Projections.fields( Projections.include( "${Theater::location.name}.${Theater.Location::address.name}.${Theater.Location.Address::city.name}"), Projections.excludeId() ) val geoWithinComparison = Filters.geoWithin( "${Theater::location.name}.${Theater.Location::geo.name}", longIslandTriangle ) val resultsFlow = collection.find<TheaterResults>(geoWithinComparison) .projection(projection) resultsFlow.collect { println(it) }
TheaterResults(location=Location(address=Address(city=Baldwin)))) TheaterResults(location=Location(address=Address(city=Levittown))) TheaterResults(location=Location(address=Address(city=Westbury))) TheaterResults(location=Location(address=Address(city=Mount Vernon))) TheaterResults(location=Location(address=Address(city=Massapequa)))
A figura a seguir mostra o polígono definido pela variável longIslandTriangle
e os pontos que representam as localizações dos cinemas retornados por nossa query.
Para mais informações sobre o operador $geoWithin
, consulte a documentação de referência para $geoWithin
Para obter mais informações sobre os operadores que você pode usar em sua query, consulte a página de manual do servidor MongoDB em operadores de query geoespacial