Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to store GPS coordinate and search places in a radius from a NoSQL DBMS (like DynamoDB)

My team needs a DBMS like DynamoDB to store large amount of data, principally places and coordinates. I've considered to use some GIS-based DBMS (like PostGIS) with an index on the POINT, but DynamoDB seems great for our use.

What is the best method to store the coordinate and quickly retrieve all objects in a particular radius?

In PostGIS it's easy, something like this:

SELECT *
FROM places
WHERE ST_DWithin(coordinate, ST_GeomFromText('POINT(45.07085 7.68434)', 4326), 100.0);

How can I do something like that in a NoSQL DBMS?

like image 290
Marco Sero Avatar asked May 21 '12 19:05

Marco Sero


2 Answers

We had the same issue, we're using AWS and DynamoDB in particular. We solved that problem by using CloudSearch Service, every time we store some 'geo-searchable' data in our database we index the data in a CloudSearch instance with lat,lon as filters ( to do this you have to do a transformation on lat and lon to turn it into a uint ).

Then let's say you want to do a search on a particular lat/lon and radius you compute the corresponding geobox ( latmin, latmax , lonmin, lonmax ) and query your CloudSearch instance with the specific filters to retrieve the key schema of your data, you can then query DynamoDB to get the information.

Some code in Java to do just the above :

Using RectangularWindows from the com.javadocmd.simplelatlng.window package by Tyler Coles, computing the bounding box and doing the transformation for lat / lon .

RectangularWindow rectangularWindow = new RectangularWindow(newLatLng(location.getLat().doubleValue(), location.getLon().doubleValue()), radius.doubleValue(), radius.doubleValue(), LengthUnit.KILOMETER);
latMin = (long) ((180 + rectangularWindow.getMinLatitude()) * 100000);     
latMax = (long) ((180 + rectangularWindow.getMaxLatitude()) * 100000);
lonMin = (long) ((360 + rectangularWindow.getLeftLongitude()) * 100000);
lonMax = (long) ((360 + rectangularWindow.getRightLongitude()) * 100000);

Then an example of a query on the CloudSearch instance :

http://[SEARCHURL]/2011-02-01/search?bq=(and lat:22300347..22309340 (and lon:28379282..28391589))

I'm not sure it's the best solution but that's what we came up with

like image 131
Eras Avatar answered Oct 05 '22 19:10

Eras


You could use geohashing to do queries of nearby objects based on strings rather than calculations.

Geohash will allow you store the location of nodes into "buckets" which can then be queried by using strings as a range or hash key in dynamodb.

Here is a good example https://github.com/davetroy/geohash-js done in javascript which can easily be rewritten in other languages.

like image 44
user896993 Avatar answered Oct 05 '22 20:10

user896993