Step by step radial location querying with MongoDB

MongoDB is great for computing geolocation using geospatial data

Basicaly you use `$geoWithin:` with `$centerSphere:` on collection with **2dsphere** index. But lets go step by step.

Scenario: Lets pretend a user is browsing hotels in his area… He want to display hotels that are in 50 mile range from his current location and your database app is full of hotels data. You would probably would use some MAP API to display them on the map (if that’s what you after be sure to check out links at the bottom) but for this example we just just want to fetch hotels data with in 50 miles range from hotels location in your MongoDB database.

First create test document collection ‘hotels’

* You might want to edit coordinates to those matching your nearby locations if you want this code to work without any change in radius distance.

// Your 'hotels' collection could look something like this:
db.hotels.insertMany([
  {
    'name': 'Golebiewski',
    'address': 'Poland, Mikolajki',
    'location': { type: "Point", coordinates: [ 40, 5.000001 ] },
    'tel': '000 000 000'
  },
  {
    'name': 'Baltazar',
    'address': 'Poland, Pultusk 36',
    'location': { type: "Point", coordinates: [ 40, 5.000002 ] },
    'tel': '000 000 000'
  },
  {
    'name': 'Zamek',
    'address': 'Poland, Pultusk',
    'location': { type: "Point", coordinates: [ 40, 5.000003 ] },
    'tel': '000 000 000'
  },
])

Then index location with 2dsphere

db.places.createIndex( { location : "2dsphere" } )

Now query based on miles range and your location.

Get your tools ready first:

// custom function - convert miles to radian
let milesToRadian = function(miles){
    var earthRadiusInMiles = 3963;
    return miles / earthRadiusInMiles;
};

// or custom function - convert km to radian
let kmToRadian = function(miles){
    var earthRadiusInMiles = 6378;
    return miles / earthRadiusInMiles;
};


// custom function - returns array with current user geolocation points - [latitude, longitude]
function getUserLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function (position) {
      let geoPoints = [position.coords.latitude, position.coords.longitude];
      console.log(geoPoints);
      return geoPoints;
    });
  } else { 
    console.log("Geolocation is not supported by this browser.");
  }
}

Now use your new tools to create query for MongoDB geospatial data.

var query = {'location' : {$geoWithin: { $centerSphere:  getUserLocation(), milesToRadian(50) ]}}}

// MongoDB example query could look something like:
// {'location': {$geoWithin: { $centerSphere: [ [ 40.000000001, 5.000000001 ], 0.012616704516780217 ]}}}

db.hotels.find(query);

MongoDB returns list of documents (hotels) with in 50 miles range from user location. Just remember that your document need to implement GeoJSON structure for storing location and it needs to be index 2dsphere. Result will be sorted by distance from user – ASC.

Output

{ "_id" : ObjectId("5d3130f810050424d26836d6"), "name" : "Golebiewski", "address" : "Poland, Mikolajki", "location" : { "type" : "Point", "coordinates" : [ 40, 5.000001 ] }, "tel" : "000 000 000" }
{ "_id" : ObjectId("5d3130f810050424d26836d7"), "name" : "Baltazar", "address" : "Poland, Pultusk 36", "location" : { "type" : "Point", "coordinates" : [ 40, 5.000002 ] }, "tel" : "000 000 000" }
{ "_id" : ObjectId("5d3130f810050424d26836d8"), "name" : "Zamek", "address" : "Poland, Pultusk", "location" : { "type" : "Point", "coordinates" : [ 40, 5.000003 ] }, "tel" : "000 000 000" }

Watch / Read more

MongoDB – geospatial queries: https://docs.mongodb.com/manual/geospatial-queries/ https://www.youtube.com/watch?v=3xP-gzh2ck0


Go further!

Get your data on to the map. Here you have some really cool tutorials for that.

Open Street Map with MapBox API: https://docs.mapbox.com/help/tutorials/building-a-store-locator/

Google Maps with Google JavaScript API: https://developers.google.com/maps/documentation/javascript/marker-clustering

If you want to convert address to geocode points, you can use Nominatim gui or Nominatim API

For example search for “Poland Pultusk” in browser or request a json response by adding to a string parameter &format=json

https://nominatim.openstreetmap.org/search.php?q=Poland+Pultusk https://nominatim.openstreetmap.org/search.php?q=Poland+Pultusk&format=json

Ps. MapBox is free up to 50k loads per month then $5 / 1000 API calls. Google gives you $200 MONTHLY CREDIT FREE USAGE which comes to 28k free API calls then 7$ / 1000 api calls. Pick your weapon and have fun :>.

Tools: MongoDB Compass (*not the community edition) https://www.mongodb.com/blog/post/visualizing-your-data-with-mongodb-compass

0
Would love your thoughts, please comment.x
()
x