O Google Maps API permite utilizar a maioria das funcionalidades disponíveis no site do Google Maps para criar aplicações com a capacidade, entre outras coisas, de recuperar a latitude e longitude de um endereço, adicionar um marcador em um mapa, criar uma área (um polígono ou um círculo) e calcular a distância entre dois pontos.

O MongoDB, cujo nome vem de humongous uma gíria americana para descrever algo muito grande, foi criado em 2009 e atualmente é o banco de dados do tipo NoSQL mais usado no mundo. Seu código é aberto e pode ser utilizado em distintas plataformas e clientes de linguagem. Além disso, o MongoDB utiliza JSON para descrever e armazenar documentos.

Primeiramente, vamos criar a página HTML para inserir os dados do passageiro. Essa página receberá o nome e o endereço do passageiro. O processo de descobrir a posição geográfica a partir do endereço é denominado geoposicionamento, e a API do Google Maps nos auxilia nesse processo.

Para utilizar a API do Google Maps, devemos ter um cadastro prévio no Google. Nessa página, podemos criar uma chave de acesso ao Google Maps API.

Tendo essa chave de acesso, vamos importar para a nova página os scripts do Google Maps API. Devemos adicionar o CSS, a biblioteca de jQuery e, principalmente, a API para a qual devemos passar a chave – coloque sua chame em - criada anteriormente, conforme explicado na Listagem 1.


<link href='http://fonts.googleapis.com/css?family=
Open+Sans:400,300,600,700,800' 
rel='stylesheet' type='text/css'>
<script src="http://maps.googleapis.com/maps/api/js?key=
<CHAVE>&sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/
jquery/2.1.1/jquery.min.js"></script>
Listagem 1. Scripts do Google Maps API

Na Listagem 2 apresenta-se como criar a página usando geocodificação - em inglês geocoder -, que irá retornar valores de latitude e longitude a partir do endereço inserido em uma página – nesse caso, não apresentamos o código HTML, mas espera-se que haja das caixas de texto: location, que conterá o endereço do passageiro e user, que conterá o nome do passageiro. Os valores retornados por essa função serão enviados ao servidor Node.js – através de uma chamada GET -, que os inserirá no MongoDB apresentado mais adiante.


  function getLatLong(){
        var geo = new google.maps.Geocoder;
        //valor vindo da caixa de texto chamada location
        var address = $('#location').val();
        var user = $('#user).val();
         
        geo.geocode({'address':address},function(results, status){
        if (status == google.maps.GeocoderStatus.OK) {
              var lat = results[0].geometry.location.lat();
              var lng = results[0].geometry.location.lng();
   
              var latlng = new google.maps.LatLng(lat,lng);
   
              var mapProp = {
                    center:latlng,
                    zoom:18,
                    mapTypeId:google.maps.MapTypeId.ROADMAP,
                    mapTypeControl: false
              };
               
              var map=new google.maps.Map(document.getElementById("googleMap"),mapProp);
              var marker = new google.maps.Marker({
                    position: latlng,
                    map: map,
                    title:name
              });
              
              $.get( "http://localhost:1346?nome="+user+"&lat="+lat+"&lon="+lng, null);   
        } else {
              //alert("O Geocoder falhou: " + status);
        }
        });
  }
Listagem 2. Função de geoposicionamento

Para utilizar o MongoDB devemos previamente instalar esse gerenciador de documentos. Nesse artigo vamos utilizar Ubuntu, porém o MongoDB pode ser instalado também em outros Linux e no Windows. A Tabela 1 apresenta uma breve descrição da sequência de comandos que vamos utilizar para instalar o MongoDB.

Comando Descrição
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 Importar a chave pública do repositório do MongoDB
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list Criar uma lista para o MongoDB
sudo apt-get update Atualizar o APT com o novo repositório e a nova lista
sudo apt-get install -y mongodb-org Instalar o MongoDB
sudo service mongod start Iniciar o MongoDB
/var/log/mongodb/mongod.log Verificar se o MongoDB foi iniciado com sucesso. Em caso positivo, a última linha do arquivo de log deve ser [initandlisten] waiting for connections on port 27017
mongo Entra no shell
use devmedia Alterna para o banco de dados denominado devmedia
Tabela 1. Comandos para instalação do MongoDB no Ubuntu

O próximo passo é criar uma collection – que pode ser entendia com a correspondente da tabela nos bancos de dados baseados em SQL. Para criar essa collection, devemos entrar no console de comandos do MongoDB e executar os comandos da Listagem 3. O comando irá criar uma collection do tipo capped chamada passageiros, cujo tamanho máximo será 5242880 bytes. Essa coleção poderá receber uma quantidade imensa de dados simultâneos para escrita, leitura ou exclusão, pois esse tipo de coleção – do tipo capped -, atua como uma lista circular, na qual os dados podem ser escritos incessantemente, já que os valores mais antigos serão sobrescritos, se necessário, para manter o limite dentro do tamanho especificado. Este recurso é extremamente útil para registros de log, dados de streaming e aplicações em tempo real.


db.createCollection("passageiros", { capped : true, 
size : 5242880, max : 5000 } )
Listagem 3. Criação de uma capped collection

Essa collection irá receber documentos JSON que vão representar a posição dos passageiros inseridas na Listagem 2. Através do da linha de comandos podemos inserir valores a essa collection, conforme ilustrado na Listagem 4. Essa inserção utilizar o padrão chamado GeoJSON para inserir a posição do passageiro recuperado na Listagem 3. Nesse exemplo criamos um ponto usando valores de latitude e longitude, contudo o GeoJSON permite criar também linhas e polígonos.


  db.passageiros.insert(
  {
  _id: "P1",
  "nome": "João da Silva",
  "loc": {
  type: "Point",
  "coordinates": [125.6, 10.1]
  } 
  }
  {
    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [125.6, 10.1]
    },
    "properties": {
      "name": "João da Silva"
    }
  }
  ) 
   
  db.passageiros.find() 
Listagem 4. Inserção de valores na collection passageiros, chamado inserir.js

Na sequência vamos integrar o Google Maps API usando o driver de Node.js para MongoDB. Como explicado na Tabela 2, a primeira providência é instalar o Node.js e o driver chamado MongoJS.

Comando Descrição
sudo apt-get install nodejs Instalar o Node.js
sudo apt-get install npm Instalar o npm, o gerenciador de pacotes do Node.js
npm install mongodb Instalar o MongoJS
npm install jquery Instalar a integração de Node.js com JQuery
nodejs inserir.js Iniciar a execução do script de node.js
Tabela 2. Comandos para instalação do Node.js

Com o driver instalado, podemos criar um novo arquivo Node.js (para iniciar esse arquivo execute nodejs inserir.js) responsável por enviar as informações ao MongoDB, ou seja, recuperamos o nome do passageiro, sua latitude, sua longitude e através do driver as inserimos na collection passageiros. As primeiras linhas da Listagem 5 - como indicado pelos comentários – realiza a conexão com o MongoDB. Na sequência usando o cliente criado – chamado MongoClient, onde vamos criar um documento no formato JSON com os valores de nome, latitude e longitude e, finalmente, realizar a inserção no MongoDB.


  var http = require('http');
  var url = require('url');
  http.createServer(function (req, res) {
       var url_parts = url.parse(req.url, true);
       var query = url_parts.query;
   
       var latitude = query.lat;
       var longitude = query.lon;
       var usuario = query.nome;
   
       // Retrieve
       var MongoClient = require('mongodb').MongoClient;
   
       //Conexão ao MongoDB
       MongoClient.connect("mongodb://localhost:27017/devmedia", function(err, db) {
       if(err) { return console.dir(err); }
   
       //Escolher a collection passageiros
       var collection = db.collection('passageiros');
       var doc = {
  'nome": usuario,
  'loc': {
  'type': 'Point',
  'coordinates': [latitude, longitude]
  }
   
  collection.insert(doc , { w: 0 });
   
  });}).listen(1346, '0.0.0.0');
  console.log('Server running at http 0.0.0.0:1346:'); 
Listagem 5. Inserção de valores na collection passageiros

A próxima tarefa e criar uma página que apresente em um mapa as posições dos passageiros que foram inseridas anteriormente. A Listagem 6 apresenta a função recuperaPassageiros.js (para iniciar esse arquivo execute nodejs recuperaPassageiros.js), que também irá criar uma conexão com o MongoDB e definir a collection passageiros como alvo. Além disso, essa função executara um comando de find para buscar todas as localizações que estão armazenadas no nosso banco de dados. Finalmente, o resultado desse comando será uma lista chamada itens que será enviada a função apresentaLocalizacoes.


  var http = require('http');
   
  http.createServer(function (req, res) {
   
  // Retrieve
  var MongoClient = require('mongodb').MongoClient;
   
  // Connect to the db
  MongoClient.connect("mongodb://localhost:27017/devmedia", function(err, db) {
  if(err) { return console.dir(err); }
   
  var collection = db.collection('passageiros');
   
  collection.find().toArray(function(err, docs){
   
  res.writeHead(200, {
                  'Content-Type': 'text/html',
                  'Access-Control-Allow-Origin' : '*'});
   
  var intCount = docs.length;
  console.log(intCount);
  if(intCount > 0){
       res.write("[");
       for(var i=0; i<intCount;i++){
            var jsonText = JSON.stringify({nome: docs[i].properties
            .name.toString(),lat:docs[i].geometry.coordinates[0]
            .toString(),lon:docs[i].geometry.coordinates[1].toString()});
            
            console.log(jsonText);
            res.write(jsonText);
            if(i!=intCount-1) res.write(",");
       }
       res.write("]");
  }
   
  res.end();
  });});}).listen(1345, '0.0.0.0');
  console.log('Server running at http00.0.0.1:1345:'); 
Listagem 6. Recuperação do posicionamento dos passageiros

Agora vamos voltar a API do Google Maps para apresentar os valores armazenados no MongoDB. Em uma nova página vamos adicionar os mesmos scripts apresentados na Listagem 1. Na sequência, conforme comentado no código da Listagem 7, vamos criar um objeto Map, que é o valor mais básico para a API do Google Maps. Esse mapa tem como propriedades o tipo que será um ROADMAP (um mapa de estradas igual ao padrão do Google Maps), e vamos desligar a possibilidade de o usuário modificar o tipo de mapa, em mapTypeControl: false. Para adicionar as posições de cada passageiro no mapa vamos utilizar um objeto do tipo Marker provido pela API do Google Maps. Cada marker vai receber a latitude e longitude e apresentar o nome do passageiro.


  <!DOCTYPE html>
  <html>
  <head>
  <link href='http://fonts.googleapis.com/css?family=
  Open+Sans:400,300,600,700,800' rel='stylesheet' type='text/css'>
        <script src="http://maps.googleapis.com/maps/api/js?
        key=<CHAVE>&sensor=false"></script>
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/
  2.1.1/jquery.min.js"></script>
   
  <script>
   
  function apresentaLocalizacoes() {
   
  $.get( "http://localhost:1345/", function( data ) {
              
              var lat=-20.1;
              var lon=50.1;
   
              var myLatlng = new google.maps.LatLng(lat, lon);
              var mapProp = {
                          center:myLatlng,
                          zoom:5,
                          mapTypeId:google.maps.MapTypeId.ROADMAP,
                          mapTypeControl: false
              };
   
              //criando objeto mapa
              var map=new google.maps.Map(document
              .getElementById("googleMap"),mapProp);
              
              var obj = jQuery.parseJSON(data);
              
              $.each($.parseJSON(data), function(idx, obj) {
              
                          var lat=obj.lat;
                          var lon=obj.lon;
              
                          var myLatlng = new google.maps.LatLng(lat, lon);
                          
                          var marker = new google.maps.Marker({
                                     position: myLatlng,
                                     map: map,
                                     title: obj.nome
                          });
              });
              
  });
   
  }
   
  </script>
  </head>
  <body onload='apresentaLocalizacoes()'>
  <div id="googleMap" style="position:fixed;
  top:0px;left:0px;width:100%;height:700px;">
  </body>
  </html>
Listagem 7. Apresentação das posições no Google Maps
Apresentação das posições no Google Maps
Figura 1. Apresentação das posições no Google Maps

A Figura 1 apresenta a localização dos passageiros em um mapa do Google maps.

Obviamente, essa aplicação não é suficiente para ajudar usuários que estejam buscando taxi. Assim, podemos criar também a interface para que taxistas informem a sua posição. Para tal, vamos criar uma nova collection chamada taxis, conforme ilustrado na Listagem 8.


db.createCollection("passageiros", { capped : true, size 
: 5242880, max : 5000 } ) 
Listagem 8. Criação da capped collection taxis

Na sequência vamos criar uma função em Node.js, de forma parecida aos códigos apresentados anteriormente. Na Listagem 9 vamos receber a posição na qual o taxi se encontra em determinado momento e registrar essa posição e o nome do taxista naquele momento. Vamos ocultar o código HTML, pois tem as mesmas características da Listagem 2.


  var http = require('http');
  var url = require('url');
  http.createServer(function (req, res) {
       var url_parts = url.parse(req.url, true);
       var query = url_parts.query;
   
       var latitude = query.lat;
       var longitude = query.lon;
       var taxista = query.taxista;
   
       // Retrieve
       var MongoClient = require('mongodb').MongoClient;
   
       //Conexão ao MongoDB
       MongoClient.connect("mongodb://localhost:27017/devmedia", function(err, db) {
       if(err) { return console.dir(err); }
   
       //Escolher a collection taxi
       var collection = db.collection(taxis);
       var doc = {
            'type': 'Feature',
            'geometry': {
                  'type': 'Point',
                  'coordinates': [latitude, longitude]
            },
            'properties': {
            'name': taxista
            }
       }
   
  collection.insert(doc , { w: 0 });
   
  });}).listen(1346, '0.0.0.0');
  console.log('Server running at http 0.0.0.0:1346:'); 
Listagem 9. Inserção de valores na collection taxi

Com a localização dos taxistas registrados no MongoDB podemos, baseado no posicionamento de um passageiro, recuperar quais são os taxistas mais próximos. Novamente vamos criar uma função node.js para realizar essa busca e retornar os valores esperados. O primeiro passo e conectar-se a colection taxis do banco de dados devmedia. Com isso, podemos enviar uma consulta que irá filtrar usando o operador $near. Esse operador irá receber a posição atual do passageiro e retornar os taxis mais próximos a ele em uma lista.


  var http = require('http');
   
  http.createServer(function (req, res) {
   
       var url_parts = url.parse(req.url, true);
       var query = url_parts.query;
   
       var latitude = query.lat;
       var longitude = query.lon;
   
  // Retrieve
  var MongoClient = require('mongodb').MongoClient;
   
  // Connect to the db
  MongoClient.connect("mongodb://localhost:27017/devmedia", 
  function(err, db) {
  if(err) { return console.dir(err); }
   
  var taxis = db.collection('taxis');
   
  taxis.find({ loc: { $near: [latitude, longitude ] } })
  .toArray(function(err, docs){
   
  res.writeHead(200, {
                  'Content-Type': 'text/html',
                  'Access-Control-Allow-Origin' : '*'});
   
  var intCount = docs.length;
  console.log(intCount);
  if(intCount > 0){
       res.write("[");
       for(var i=0; i<intCount;i++){
            var jsonText = JSON.stringify({nome: docs[i]
            .properties.name.toString(),lat:docs[i].geometry
            .coordinates[0].toString(),lon:docs[i].geometry
            .coordinates[1].toString()});
            
            console.log(jsonText);
            res.write(jsonText);
            if(i!=intCount-1) res.write(",");
       }
       res.write("]");
  }
   
  res.end();
  });});}).listen(1347, '0.0.0.0');
  console.log('Server running at http00.0.0.1:1347:');
Listagem 10. Recuperação do posicionamento dos taxistas mais próximos de um passageiro

No Google Maps poderemos agora apresentar os resultados da Listagem 10diretamente no mapa. A função da Listagem 11 pode ser alterada a fim de diferenciar os marcadores de taxis em relação aos marcadores de passageiros.

 
<!DOCTYPE html>
<html>
<head>
<link href='http://fonts.googleapis.com/css?family=
Open+Sans:400,300,600,700,800' 
rel='stylesheet' type='text/css'>
    <script src="http://maps.googleapis.com/maps/api/
    js?key=<CHAVE>&sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/
jquery/2.1.1/jquery.min.js"></script>
 
<script>
 
function apresentaTaxis() {
 
$.get( "http://localhost:1347/", function( data ) {
            
            var lat=-20.1;
            var lon=50.1;
 
            var myLatlng = new google.maps.LatLng(lat, lon);
            var mapProp = {
                        center:myLatlng,
                        zoom:5,
                        mapTypeId:google.maps.MapTypeId.ROADMAP,
                        mapTypeControl: false
            };
 
            //criando objeto mapa
            var map=new google.maps.Map(document
            .getElementById("googleMap"),mapProp);
            
            var obj = jQuery.parseJSON(data);
            
            $.each($.parseJSON(data), function(idx, obj) {
            
                  var lat=obj.lat;
                  var lon=obj.lon;
      
                  var myLatlng = new google.maps.LatLng(lat, lon);
                  
                  var marker = new google.maps.Marker({
                             position: myLatlng,
                             map: map,
                             title: obj.nome
                  });
            });
            
});
 
}
 
</script>
</head>
<body onload='apresentaLocalizacoes()'>
<div id="googleMap" style="position:fixed;top:0px;left:0px;width:100%;height:700px;">
</body>
</html>
Listagem 11. Apresentação das posições no Google Maps

Esse exemplo pode ser expandido usando as capacidades do MongoDB para calcular a distância de pontos, verificar se um passageiro está na área de atuação de taxistas ou mesmo para criar uma aplicação Android para recuperar automaticamente os valores de latitude e longitude diretamente do GPS. Além disso, poderíamos utilizar o documento recuperado do MongoDB usando o a função map.data.loadGeoJson da API do Google Maps, que carrega os pontos diretamente do documento GeoJSON.