Visão geral
Neste guia, você pode aprender como query dados geoespaciais usando o driver Scala. Você também pode aprender sobre diferentes formatos de dados geoespaciais suportados pelo MongoDB.
Os dados geoespaciais 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
Dados de amostra
Os exemplos neste guia usam a theaters collection no sample_mflix banco de dados dos conjuntos de dados de amostra do Atlas . Para acessar essa collection a partir do seu aplicação Scala, crie um MongoClient que se conecte a um Atlas cluster e atribua os seguintes valores às suas variáveis database e collection:
val database: MongoDatabase = mongoClient.getDatabase("sample_mflix") val collection: MongoCollection[Document] = database.getCollection("theaters")
Para aprender a criar um cluster MongoDB Atlas gratuito e carregar os conjuntos de dados de amostra, consulte o Guia de Introdução do MongoDB.
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:
"location" : { "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 é 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.
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: Posição única. Isso pode representar a localização de uma construção.LineString: Array de duas ou mais posições, formando uma série de segmentos de linha. Isso pode representar a rota da Grande Muralha da China.Polygon: 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 GeoJSON no manual do servidor.
Index
Para criar um índice 2dsphere , utilize o auxiliar Indexes.geo2dsphere() para criar uma especificação para o índice 2dsphere . Passe a especificação para o método MongoCollection.createIndex() para criar o índice.
O exemplo seguinte cria um índice 2dsphere no campo "location.geo" na coleção theaters :
val indexObservable = collection.createIndex(Indexes.geo2dsphere("location.geo")) Await.result(indexObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
Para saber mais sobre índices no driver Scala, consulte o guia Otimizar queries usando índices.
Coordenadas em um plano 2D
Você pode armazenar dados geoespaciais usando coordenadas x e y em um plano Euclidiano bidimensional. As coordenadas em um plano bidimensional são chamadas de legacy coordinate pairs.
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.
Index
Para dados de query armazenados como legacy coordinate pairs, você deve adicionar o campo contendo legacy coordinate pairs a um índice 2d. O seguinte trecho de código cria um índice 2d no campo coordinates utilizando o objeto Indexes:
val indexObservable = collection.createIndex(Indexes.geo2d("coordinates")) Await.result(indexObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
Para saber mais sobre índices no driver Scala, consulte o guia Otimizar queries usando índices.
Para mais informações sobre pares de coordenadas legado, consulte a seção pares de coordenadas legado do guia de queries 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.
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$geoIntersectsrequer um índice de 2dsphere
Você pode especificar esses operadores de query no driver Scala com os métodos near(), geoWithin(), nearSphere() e geoIntersects() do objeto 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 ver uma lista completa dos métodos assistente Filters, consulte a documentação da API 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 Scala.
Para saber mais sobre as classes de forma GeoJSON, consulte a documentação da API do pacote GeoJSON.
Exemplos de query geoespacial
Os exemplos a seguir utilizam a coleção theaters do MongoDB Atlas no banco de dados de amostra sample_mflix. Você pode aprender como configurar seu próprio cluster do Atlas de camada grátis e como carregar o conjunto de dados de amostra no guia Introdução ao Scala Driver.
Os exemplos nesta seção exigem as seguintes importações:
import org.mongodb.scala.* import org.mongodb.scala.model.Indexes import org.mongodb.scala.model.Filters import org.mongodb.scala.model.Projections import com.mongodb.client.model.geojson.{Point, Polygon, Position} import java.util.Arrays import java.util.concurrent.TimeUnit import scala.concurrent.Await import scala.concurrent.duration.Duration
A collection theaters já contém um índice 2dsphere no campo location.geo .
Query por proximidade
Para pesquisar e retornar documentos do mais próximo ao mais distante de um ponto, use o método near() do objeto Filters. O método near() constrói uma query com o operador de query $near.
O exemplo a seguir retorna documentos que estão a no máximo 1000 metros da instância GeoJSON Point especificada, classificados do mais próximo para o mais distante:
val refPoint = new Point(new Position(-73.986805, 40.7620853)) val findObservable = collection.find(Filters.near("location.geo", refPoint, Some(1000.0), Some(0.0))) val results = Await.result(findObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
{"_id": {"$oid": "59a47287cfa9a3a73e51e8e2"}, "theaterId": 1908, "location": {"address": {"street1": "750 Seventh Ave", "city": "New York", "state": "NY", "zipcode": "10019"}, "geo": {"type": "Point", "coordinates": [-73.983487, 40.76078]}}} {"_id": {"$oid": "59a47286cfa9a3a73e51e838"}, "theaterId": 1448, "location": {"address": {"street1": "1880 Broadway", "city": "New York", "state": "NY", "zipcode": "10023"}, "geo": {"type": "Point", "coordinates": [-73.982094, 40.769882]}}}
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.
Query dentro de um intervalo
Para pesquisar dados geoespaciais dentro de uma forma especificada, use o método geoWithin() do objeto Filters. O método geoWithin() constrói uma query com o operador de query $geoWithin.
O exemplo a seguir pesquisa cinemas em uma seção de Long Island. O exemplo aplica uma projeção para que cada resultado inclua apenas o campo location.address.city e exclua o campo _id:
val longIslandTriangle = new Polygon(Arrays.asList( new Position(-72.0, 40.0), new Position(-74.0, 41.0), new Position(-72.0, 39.0), new Position(-72.0, 40.0) )) val projection = Projections.fields( Projections.include("location.address.city"), Projections.excludeId() ) val geoWithinComparison = Filters.geoWithin("location.geo", longIslandTriangle) val findObservable = collection.find(geoWithinComparison).projection(projection) val results = Await.result(findObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) results.foreach(doc => println(doc.toJson()))
{"location": {"address": {"city": "Baldwin"}}} {"location": {"address": {"city": "Levittown"}}} {"location": {"address": {"city": "Westbury"}}} {"location": {"address": {"city": "Mount Vernon"}}} {"location": {"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 que a query retorna.

Para saber mais sobre o operador $geoWithin, consulte a referência $geoWithin no manual do servidor.
Informações adicionais
Para saber mais sobre como executar queries geoespaciais, consulte Queries geoespaciais no manual do servidor.