Executing 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, called 2D indexes, is the simpler of the two. It assumes that the data is given as x,y coordinates. The second one. called 3D or spherical indexes, is relatively more complicated. In this recipe, we will explore 2D indexes and execute some queries on 2D data. The data on which we are going to work is a 25 X 25 grid with some coordinates representing bus stops, restaurants, hospitals, and gardens.

Executing flat plane (2D) geospatial queries in Mongo using geospatial indexes

Getting ready

Refer to the Connecting to a single node from a Java client recipe from Chapter 1, Installing and Starting the MongoDB Server, for all the necessary setup for this recipe. Download the data file named 2dMapLegacyData.json and keep it ready to import on the local filesystem. 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 2dMapLegacyData.json file is present in the current directory.
    $ mongoimport -c areaMap -d test --drop 2dMapLegacyData.json
    
  2. If we see something like the following output 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 contents 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 a 2D geospatial index on this data. Execute the following command 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 where an individual is standing. Assuming the person is not fussy about the type of cuisine, let us execute the following query, assuming that the person is standing at location (12, 8), as shown in the preceding screenshot. Also, we are interested in just the 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 as per the increasing distance. If we look at the image given earlier, we kind of agree with the results given here.
  7. Let us 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 us 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 us now go through what we did. Before we continue, let us define what exactly we mean by the distance between two points. Suppose on a cartesian plane we have two points, (x1, y1) and (x2, y2), the distance between them would be computed using the following formula:

How it works…

For example, suppose the two points are (2, 10) and (12, 3), the distance would be as follows:

How it works…

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

We started by importing the data normally into a areaMap collection in the x database and created an index as db.areaMap.ensureIndex({co:'2d'}). The index is created on the co field 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: 2D index and spherical index. A 2D index is commonly used for planes whose span is less and does not involve spherical surfaces. It could be something such as 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, as follows:

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

We will query for documents that are of type R, that is, those documents for "restaurants" and that are closest to the point (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 the top three documents. We may also provide $maxDistance in the query, which will restrict the results to 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