Storing Geo-Positioning Data with Google Maps, Node.js and MongoDB

By Diogo Souza

WEBINAR: On-demand webcast

How to Boost Database Development Productivity on Linux, Docker, and Kubernetes with Microsoft SQL Server 2017 REGISTER >

The Google Maps API allows you to use most of the features available to create applications with the ability to retrieve the latitude and longitude of an address, add a marker to a map, create an area (a polygon or a circle) and calculate the distance between two points, and more.

MongoDB, whose name comes from "humongous" in American slang to describe something very large, was created in 2009 and is currently the most-used NoSQL-like database in the world. Its code is open and can be used across platforms and language clients. In addition, MongoDB uses JSON to describe and store documents.

Getting Started with Geo-Positioning

First, let's create the HTML page to enter the passenger data. This page will receive the name and address of the passenger. The process of discovering geographic position from the address is called geo-positioning, and the Google Maps API helps us in this process.

To use the Google Maps API, we must have a previous Google registration and go to https://developers.google.com/maps/signup. On this page, we can create a Google Maps API access key. Once we have the access key, we'll import the Google Maps API scripts into the new page. We should add the CSS, the jQuery library and, most importantly, the API to which we must pass the key — put your call in — created earlier, as explained in Listing 1.

Listing 1. Maps API Scripts

<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>

Listing 2 shows how to create the page using geocoder, which will return latitude and longitude values from the address entered on a page, in which case we do not display the HTML code, but we expect that there will be of the text boxes:

  • location, which will contain the address of the passenger and
  • user, which will contain the name of the passenger.

The values returned by this function will be sent to the Node.js server via a GET call that will insert them into the MongoDB shown later.

Listing 2. Geo-positioning function

function getLatLong(){
        var geo = new google.maps.Geocoder;
        // value that comes from a textbox called 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("Geocoder failed: " + status);
        }
        });
  }

In order to use MongoDB, we must first install the document manager. In this article we will use Ubuntu, however MongoDB can also be installed on either Linux and Windows.

Create a Collection

The next step is to create a collection — that can be understood as the corresponding table in SQL-based databases. To create this collection, we must enter the MongoDB command console and execute the commands in Listing 3. The command will create a capped type collection called "passengers," whose maximum size will be 5242880 bytes. This collection can receive an immense amount of concurrent data for writing, reading, or deletion. Since this type of collection — of the capped type — acts as a circular list, in which data can be written incessantly, and since the oldest values will be overwritten if necessary, to keep the limit within the specified size. This feature is extremely useful for log records, streaming data and real-time applications.

Listing 3. Creating a capped collection

db.createCollection("passengers", { capped : true, size : 5242880, max : 5000 } ) 

This collection will receive JSON documents that will represent the position of the passengers inserted in Listing 2. Through the command line we can insert values to this collection, as shown in Listing 4. This insert uses the standard called GeoJSON to insert the position of the passenger retrieved in Listing 3.

In this example, we created a point using latitude and longitude values, however, GeoJSON allows you to also create lines and polygons.

Listing 4. Insertion of values in the collection passengers, named insert.js

db.passageiros.insert(
  {
  _id: "P1",
  "nome": "Mary Anne",
  "loc": {
  type: "Point",
  "coordinates": [125.6, 10.1]
  } 
  }
  {
    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [125.6, 10.1]
    },
    "properties": {
      "name": "Mary Anne"
    }
  }
  ) 
   
  db.passageiros.find()

Next we will integrate the Google Maps API using the Node.js driver for MongoDB. The first step is to install Node.js and the driver called MongoJS:

sudo apt-get install nodejs // Installs Node.js
sudo apt-get install npm // Installs npm
npm install mongodb // Installs MongoJS
npm install jquery // Installs the integration of Node.js with JQuery
nodejs insert.js // Start the node.js script

With the driver installed, we can create a new file Node.js (to start this file execute nodejs insert.js) responsible for sending the information to MongoDB. That is, we retrieve the name of the passenger, his or her latitude and length, then we insert them in the passenger collection via the driver. The first few lines of Listing 5, as indicated by the comments, connect to MongoDB. In the sequence using the created client, called MongoClient, where we will create a document in the JSON format with the name, latitude and longitude values and finally perform the insertion in MongoDB.

Listing 5. Inserting values into the collection passengers

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 user = query.nome;

   // Retrieve
   var MongoClient = require('mongodb').MongoClient;

   // MongoDB connection
   MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
   if(err) { return console.dir(err); }

   // Choose a passengers collection
   var collection = db.collection('passengers');
   var doc = {
	'nome": user,
	'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:'); 

The next task is to create a page that displays the positions of the passengers that were previously entered on a map. Listing 6 shows the function retrievePassengers.js (to start this file execute nodejs retrievePassengers.js), which will also create a connection with MongoDB and set the passenger collection as a target. In addition, this function will execute a find command to fetch all the locations that are stored in our database. Finally, the result of this command will be a list called items that will be sent to the showLocalizations function.

Listing 6. Getting the passengers positioning

var http = require('http');
   
http.createServer(function (req, res) {

// Retrieve
var MongoClient = require('mongodb').MongoClient;

// Connect to the db
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
if(err) { return console.dir(err); }

var collection = db.collection('passengers');

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({name: 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:'); 

Now let's go back to the Google Maps API to display the values stored in MongoDB. In a new page we will add the same scripts presented in Listing 1. In the sequence, as commented in the code in Listing 7, we will create a Map object, which is the most basic value for the Google Maps API. This map has properties like the type that will be a ROADMAP (a roadmap equal to Google Maps default), and we will turn off the possibility of the user modifying the map type, in "mapTypeControl: false". To add the positions of each passenger on the map we will use a Marker object provided by the Google Maps API. Each marker will receive the latitude and longitude and display the name of the passenger.

Listing 7. Presentation of the positions in Google Maps

<!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=<KEY>&sensor=false"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<script>

function showLocalizations() {

$.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
          };

          // Creating map object
          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.name
                      });
          });
          
});

}

</script>
</head>
<body onload='showLocalizations()'>
<div id="googleMap" style="position:fixed;top:0px;left:0px;width:100%;height:700px;">
</body>
</html>

This example can be expanded using MongoDB's capabilities to calculate point distance, check whether a given passenger is in the taxi driver's area, or even to create an Android application to automatically retrieve latitude and longitude values directly from GPS. Good luck!

References

MongoDBGeoJSON

About the Author

Diogo Souza works as Java Developer at Fulcrum Worldwide and has worked for companies such as Indra Company, Atlantic Institute and Ebix LA. He is also an Android trainer, speaker at events on Java and mobile world and a DevMedia consultant.



Make a Comment

Loading Comments...

  • Web Development Newsletter Signup

    Invalid email
    You have successfuly registered to our newsletter.
  •  
  •  
  •  
Thanks for your registration, follow us on our social networks to keep up-to-date