Recently I was intrigued about a project discussion in which a high volume REST API was needed to store and retrieve location based information. A performant solution was need that could work with big datasets, atleast containing a few million entries.
I haven’t done much work in the Geospatial area but I thought this could be an interesting use case to get my hands dirty to learn something new. The requested API needed to be able to store location points for a subject (person). On the other hand these locations needed to be retrieved based on their proximity to a certain point (latitude and longitude).
After stumbling upon MongoDB’s support for GeoJSON, a format for encoding a variety of geographic data structures, it looked like a perfect match for this use case. High volume and performance shouldn’t be a problem for MongoDB. A GeoJSON Point (latitude, longtitude) was already supported in MongoDB since v2.4, a lot of other features and improvements have been added since then in the current v3.0. Sounds impressive, no?
I decided to start a quick prototype has contained two methods:
/locationsthat has four query parameters.
d: distance from the location and
/locationsthat has one query parameter.
s: subject and a
bodythat contains a list of locations for this specific subject.
The technologies for this prototype are:
- Spring Boot
- Spring Data MongoDB
Create a MongoDB database and add spatial index
If you installed MongoDB commandline, define your database and create an index:
Generate a basic project
Head over to Spring Initializer, or if you are using IntelliJ you can just choose to create a new Spring Boot application, and choose Spring Web, Spring Data MongoDB and Gradle. You should end up with a
build.gradle something along the lines of:
Since the Gradle Wrapper is recommended by the documentation I also used it.
Add Spring Data MongoDB repository
First let’s create a simple
LocationEntity which will be stored in MongoDB. For the sake of brevity I left out the getters/setters/equals/hashcode, you can find the full source on GitHub:
Next we need a Spring Repository that will actually query for all locations for a certain subject and a proximity near a location. This is where all the heavy lifting (magic?) has to happen.
That’s all you need, Spring Data will take care of everything based on the method name. That’s awesome, right? You pass a subject, a certain Point (longitude and latitude) and how far in distance it should look from that certain point in miles or kilometers. Spring magic at its best.
Implementing REST endpoints
As we defined before, we’ll need to two endpoints to retrieve the locations based on the repository that we just created and also create new LocationEntity entries. Let’s start with retrieving the locations:
Spring gives you a nice
RestController annotation that will make sure all the methods in the class are annotated with
ResponseBody. The only this this method do is have a few query parameters and use them to call our
LocationRepository. We have to define the metric we want to use for the
distance parameter, in our case we’ll use kilometers.
Next, we want to add locations for a certain subject
LocationEntry POJO is an object that only contains latitude and longitude, since that’s all we need for a location that will be added. Based on this POJO we created a new
GeoJsonPoint to store it in MongoDB.
With these few steps I was able to create a Geospatial Location based API prototype within a few hours, mostly spent on doing research on MongoDB and Spring Data MongoDB capabilities. I’m happy that I now know MongoDB is capable of quite a bit of Geospatial things, and that it is quite easy to use as well.
Hope you learned something new as well! You can find the source code for this example on GitHub.