How to use geo spatial with MongoDB?

Problem Statement
Find all locations that are within a certain radius of a particular location.

Solution Approach
We will demonstrate this with pseudo-code.

Let us insert lots of location specific data in MongoDB.

We will search this very data later.


static Mongo m;
static DB db;
static DBCollection coll;

m = new Mongo("localhost");
db = m.getDB("mydb");
coll = db.getCollection("people");
coll.ensureIndex((DBObject) JSON.parse("{ 'loc' : '2d' }"));

Random rand = new Random();
long startTime = Calendar.getInstance().getTimeInMillis();

for (int i = 0; i < 100000; i++) 
{
    double lat = rand.nextDouble() * 180 - 90; 
    BigDecimal bd1 = new BigDecimal(lat).setScale(2,RoundingMode.HALF_EVEN);
    lat = bd1.doubleValue();

    if (lat = 90)
         lat = lat - 0.5;
         double lon = rand.nextDouble() * 360 - 180; 
         BigDecimal bd = new BigDecimal(lon).setScale(2, RoundingMode.HALF_EVEN);
         lon = bd.doubleValue();

    if (lon = 90)
         lon = lon - 0.5;

    // System.out.println("lon / lat = " + lon + " / " + lat);
    // lat=1; lon=1;
    coll.insert((DBObject) JSON.parse("{'loc' : [ " + lon + " , " + lat	+ " ]}"), WriteConcern.SAFE);
}

long timeTaken = Calendar.getInstance().getTimeInMillis() - startTime;
System.out.println("Total Time Taken to Insert (milliseconds): " + timeTaken);

Now we want to do a geo spatial search on the above inserted data.
i.e find all documents(rows) whose location is within a certain miles(radius) from a particular location(lat,lon):

There are several ways to do this search.
Lets look at them one by one.


//Using $nearSphere to find all locations that are within 1000 miles from location 78,10

static void searchWithNearSphere() 
{
    // 1 radian = 3959 miles (6371 km).
    // So, 100 miles = 100/3959 = 0.0253 radians.
    // So, 1000 miles = 1000/3959 = 0.253 radians.
    System.out.println("searchWithNearSphere: Query to run: "
    + "{'$nearSphere' : [ 78 , 10 ] , '$maxDistance' : 0.253}");

    long startTime = Calendar.getInstance().getTimeInMillis();

    // Must use long/lat format, and not lat/long.
    // Valid bounds for latitude is -90/90.
    // Valid bounds for longitude is -180/180
    DBCursor cur = coll.find(new BasicDBObject("loc", JSON.parse("{'$nearSphere' : [ 78 , 10 ] , '$maxDistance' : 0.253}"))).limit(100000);
    long timeTaken = Calendar.getInstance().getTimeInMillis() - startTime;
    System.out.println("Total Time Taken for 'searchWithNearSphere(milliseconds): " + timeTaken);

    System.out.println("Total Documents Found: " + cur.count());
    System.out.println("Total Documents Found: " + cur.length());
    System.out.println("Total Documents Found: " + cur.size());

    /*
    * while (cur.hasNext()) { System.out.println(cur.next()); }
    * 
    * System.out.println("Total Documents Found: " + cur.size());
    */
}

// Using geoNear command to find all locations that are within 1000 miles from location 78,10
static void searchWithGeoNear() 
{
    BasicDBObject cmd = new BasicDBObject();
    cmd.put("geoNear", "people");
    int coord[] = { 78, 10 };
    cmd.put("near", coord);
    cmd.put("num", 1000);
    cmd.put("maxDistance", 0.253);
    cmd.put("spherical", true);

    long startTime = Calendar.getInstance().getTimeInMillis();
    CommandResult r = db.command(cmd);
    long timeTaken = Calendar.getInstance().getTimeInMillis() - startTime;
    System.out.println("Total Time Taken for 'searchWithGeoNear(milliseconds): " + timeTaken);
    System.out.println(r.ok());
    System.out.println(r.getErrorMessage());
    // System.out.println(r.toString());

    // print(r);//Print all the returned data.

    com.mongodb.BasicDBList resultsBasicDBList = (BasicDBList) r.get("results");
    System.out.println("Total Results: " + resultsBasicDBList.size());

    // System.out.println("Results: " + resultsBasicDBList); //This will
    // print the value of 'results' key.

    // print(resultsBasicDBList);//This will print individual values.
}

//The print function to print a DBObject:
public static void print(DBObject doc) 
{
    Set allKeys = doc.keySet();
    Iterator it = allKeys.iterator();
    while (it.hasNext()) 
    {
        Object o = it.next();
        String temp = (String) o; // it.next();
        // System.out.println("K CLASS: " + o);
        // System.out.println("V CLASS: " + doc.get(temp).getClass());
        System.out.print(temp + "-");

        if (doc.get(temp) instanceof BasicDBObject) 
        {
            System.out.println("\n");
	    print((DBObject) doc.get(temp));
        } 
        else 
        {
            System.out.println(doc.get(temp));
	    if (temp.toString().equalsIgnoreCase("loc"))
	        System.out.println("-------------");
        }
    }//end of while
}

// To clean up a collection completely

static void clean() 
{
    // clear records if any
    DBCursor cur = coll.find();

    while (cur.hasNext())
        coll.remove(cur.next());
}

Thats It!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: