Flat plane 2D geospatial queries in Mongo using geospatial indexes

In this recipe, we will see what geospatial queries are and then see how to apply these queries on flat planes. We will put it to use in a test map application.

Geospatial queries can be executed on data in which geospatial indexes are created. There are two types of geospatial indexes. The first one is called the 2D indexes and is the simpler of the two, it assumes that the data is given as x,y coordinates. The second one is called 3D or spherical indexes and is relatively more complicated. In this recipe, we will explore the 2D indexes and execute some queries on 2D data. The data on which we are going to work upon is a 25 x 25 grid with some coordinates representing bus stops, restaurants, hospitals, and gardens.

Flat plane 2D geospatial queries in Mongo using geospatial indexes

Getting ready

Refer to the recipe Connecting to the single node using a Java client from Chapter 1, Installing and Starting the Server, for all the necessary setup for this recipe. Download the data file 2dMapLegacyData.json and keep it on the local filesystem ready to import. Open a mongo shell connecting to the local MongoDB instance.

How to do it…

  1. Execute the following command from the operating system shell to import the data into the collection. The file 2dMapLegacyData.json is present in the current directory.
    $ mongoimport -c areaMap -d test --drop 2dMapLegacyData.json
    
  2. If we see something like the following on the screen, we can confirm that the import has gone through successfully:
    connected to: 127.0.0.1
    Mon Mar 17 23:58:27.880 dropping: test.areaMap
    Mon Mar 17 23:58:27.932 check 9 26
    Mon Mar 17 23:58:27.934 imported 26 objects
    
  3. After the successful import, from the opened mongo shell, verify the collection and its content by executing the following query:
    > db.areaMap.find()
    

    This should give you the feel of the data in the collection.

  4. The next step is to create 2D geospatial index on this data. Execute the following to create a 2D index:
    $ db.areaMap.ensureIndex({co:'2d'})
    
  5. With the index created, we will now try to find the nearest restaurant from the place an individual is standing. Assuming the person is not fussy about the type of cuisine, let's execute the following query assuming that the person is standing at location (12, 8), as shown in the image. Also, we are interested in just three nearest places.
    $ db.areaMap.find({co:{$near:[12, 8]}, type:'R'}).limit(3)
    
  6. This should give us three results, starting with the nearest restaurant with the subsequent ones given in increasing distance. If we look at the image given earlier, we kind of agree with the results given here.
  7. Let's add more options to the query. The individual has to walk and thus wants the distance to be restricted to a particular value in the results. Let's rewrite the query with the following modification:
    $ db.areaMap.find({co:{$near:[12, 8], $maxDistance:4}, type:'R'})
    
  8. Observe the number of results retrieved this time around.

How it works…

Let's now go through what we did. Before we continue, let's define what exactly we mean by the distance between two points. Suppose on a cartesian plane that we have two points (x1, y1) and (x2, y2), the distance between them would be computed using the formula:

√(x1 – x2)2 + (y1 – y2)2

Suppose the two points are (2, 10) and (12, 3), the distance would be: √(2 – 12)2 + (10 – 3)2 = √(-10)2 + (7)2 = √149 =12.207.

After knowing how calculations for distance calculation are done behind the scenes by MongoDB, let's see what we did right from step 1.

We started by importing the data normally into a collection, areaMap in the test database and created an index as db.areaMap.ensureIndex({co:'2d'}). The index is created on the field co in the document and the value is a special value, 2d, which denotes that this is a special type of index called 2D geospatial index. Usually, we give this value as 1 or -1 in other cases denoting the order of the index.

There are two types of indexes. The first is a 2D index that is commonly used for planes whose span is less and do not involve spherical surfaces. It could be something like a map of the building, a locality, or even a small city where the curvature of the earth covering the portion of the land is not really significant. However, once the span of the map increases and covers the globe, 2D indexes will be inaccurate for predicting the values as the curvature of the earth needs to be considered in the calculations. In such cases, we go for spherical indexes, which we will discuss soon.

Once the 2D index is created, we can use it to query the collection and find some points near the point queried. Execute the following query:

> db.areaMap.find({co:{$near:[12, 8]}, type:'R'}).limit(3)

It will query for documents that are of the type R, which are of type restaurants and closes to the co-ordinates (12,8). The results returned by this query will be in the increasing order of the distance from the point in question, (12, 8) in this case. The limit just limits the result to top three documents. We may also provide the $maxDistance in the query, which will restrict the results with a distance less than or equal to the provided value. We queried for locations not more than four units away, as follows:

> db.areaMap.find({co:{$near:[12, 8], $maxDistance:4}, type:'R'})
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset