Geospatial (location based) Searches in MongoDB – Part 2 – simple searching

April 2, 2012

This is the 2nd post of a multi-part series on performing geospatial (location based) searches on large data sets in MongoDB.

In this part we will focus on using simple queries to perform geo searches on the location tagged data that we loaded into the MongoDB (see part 1 for details).

MongoDB supports two-dimensional geospatial indexes. It is designed with location-based queries in mind, such as “find me the closest N items to my location.” It can also efficiently filter on additional criteria, such as “find the items that are within some distance of the centroid of my search”.

Assuming that the data has been properly loaded the first step it to index the data so that it can be geo searched by mongo. This can be done from Java, but for this exercise we will set it up from the command line:
db.name_of_collection.ensureIndex( { loc : “2d” } )

Once you have created the index, it is best to check and make sure that it was created properly:
db.name_of_collection.getIndexes()
You should see something like:
{ “v” : 1, “key” :
{ “loc” : “2d” },
“ns” : “geo1.um”,
“name” : “loc_”
}
Note: The key part is that “loc” should be “2d”

Now for the ‘fun part’, building and running the geospatial queries in Java. We will start simple and build more complex queries, using more advanced Java concepts (i.e. classes) as we go along. If you are not completely comfortable with building/running queries with the BasicDBObject then please review.

A simple geo search from the command line would look like: db.um.find( { loc : { $near : [15,150] }})
In java it would be:

Double locationLongitude = new Double (15);
Double locationLatitude = new Double (150);
BasicDBObject locQuery = new BasicDBObject();
locQuery.put(“loc”, new BasicDBObject(“$near”, new Double[]{locationLongitude, locationLatitude}));
// run the query
DBCursor locCursor = collectionUM.find( locQuery );
// use cursor to view results

Note: Use Double array in this approach; otherwise is can lead to precision issues.

A more complex (useful) search from the command like could be: db.um.find( { loc : { $near : [15.,-150.11] , $maxDistance : 40 } } ).limit(10)
In Java, using a JSON document:

String sLng = “15.5”; Double dLng = new Double(sLng);
String sLat = “150.11”; Double dLat = new Double(sLat);
String sDistance = “40”;
DBCursor cur = collectionUM.find(new BasicDBObject(“loc”,JSON.parse(“{$near : [ ” + dLng + “,” + dLat + ” ] , $maxDistance : ” + sDistance + “}”))).limit(10);

Note: Even with this relatively simple query, it does not appear that you can easily wrap the geo query parameters in a Java BasicDBObjec object. There have been a number of posting on Stack Overflow and the Mongo Google Groups on this issue. However, I have not yet see an example of a BasicDBObject implementation that does not have to resort to using (parsing) a JSON document. Also, there is some mention of implementing this query with the BasicDBObjectBuilder. I am currently looking to that.

In the next installment I plan to using more advanced Java concepts (i.e. classes) to implement the searches.