Menu Docs

Pesquisar geoespacialmente

Neste guia, você pode aprender como consultar dados geoespaciais usando o driver Kotlin. Você também pode aprender sobre 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

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:

"location" : {
"type": "point",
"coordinates": [-73.986805, 40.7620853]
}

Para obter informações sólidas sobre o GeoJSON,consulte a especificação oficial do IETF .

Uma posição representa um único local na Terra e é fornecida 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.

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:

Para saber mais sobre as formas que você pode usar no MongoDB, consulte GeoJSON no manual do servidor.

Para query dados armazenados no formato GeoJSON, adicione o campo que contém dados GeoJSON a um índice 2dsphere. O seguinte trecho cria um índice 2dsphere no campo location.geo utilizando o construtor Indexes:

collection.createIndex((Indexes.geo2dsphere("location.geo")))

Para saber mais sobre o construtor Indexes, consulte o guia Construtores de índices.

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 pares de coordenadas legado.

Os legacy coordinate pairs têm a seguinte estrutura:

{ "location" : [ x, y ] }

O valor do campo contém uma array de dois valores em que o primeiro representa o valor do eixo x e o segundo representa o valor do eixo y.

Para query dados armazenados como pares de coordenadas legado , você deve adicionar o campo que contém pares de coordenadas legado a um índice 2d . O seguinte trecho cria um índice 2d no campo coordinates utilizando o construtor Indexes:

collection.createIndex((Indexes.geo2d("coordinates")))

Para saber mais sobre o construtor Indexes, consulte o guia Construtores de índices.

Para mais informações sobre pares de coordenadas legado, consulte a seção Pares de Coordenadas Legadas do guia de Consultas Geoespaciais no manual do Servidor.

Dica

Operadores suportados

Os índices esféricos (2dsphere) e planos (2d) suportam alguns, mas não todos, dos mesmos operadores de query. Para visualizar uma lista completa de operadores e sua compatibilidade de índice, consulte a seção Operadores de query geoespacial do guia de queries geoespaciais no manual do servidor.

As queries geoespaciais consistem em um operador de query e formas GeoJSON como parâmetros de query.

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 saber mais sobre operadores de query geoespacial, consulte a seção Operadores de Query Geoespacial do guia de Queries Geoespaciais no manual do Servidor.

Para saber mais sobre o construtor Filters, consulte o guia Construtores de filtros.

Para especificar uma forma para utilizar em uma consulta geoespacial, utilize as classes Position, Point, LineString e Polygon do driver Kotlin .

Para saber mais sobre as classes de forma GeoJSON, consulte a documentação da API do pacote GeoJSON.

Os exemplos seguintes utilizam o conjunto de dados de amostra do MongoDB Atlas. Você pode aprender como configurar seu próprio Atlas cluster de camada grátis e como carregar o conjunto de dados de exemplo no guia Início rápido do driver Kotlin.

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 nesta seção 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 documentos de amostra são modelados pela 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 documentos de resultado são modelados pela 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}" .

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 consulta cinemas entre 10000 e 5000 metros do Grande Gramado do Central Park:

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

O MongoDB utiliza o mesmo sistema de referência que os Satélites gps para calcular geometrias sobre a Terra.

Para saber mais sobre o operador $near, consulte a referência $near no manual do servidor.

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.

Área de Long Console na qual procurar cinemas

Para saber mais sobre o operador $geoWithin, consulte a referência $geoWithin no manual do servidor.