0

I am trying to create a Bounding Box (or a circle) for the given latitude and longitude with some distance(or radius) using Python3.

I have gone through the previous solutions for this problem but I am having some doubt on how it works. There are some variables like halfsideinKm and some degree to radian and radian to degree conversion and I am unable to understand what are those conversions for and how it works.

Given lat and long finding binding box

Geocoding calculate bounding box

I have a database collection Locations(in MongoDB) which holds the lat and long.

My Requirement is if I enter a lat and long I want to have the list of Places(from my mongodb) which lie inside of the Bounding Box region(with a distance of say 20 Km).

Can anyone provide me with a solution for this problem or some explanation on how those codes work?

Can this be achieved using geopy?(because it says something about great circle distance calculation)

Database values

{
  "place_id":"151142295",
  "osm_type":"relation",
  "osm_id":"65606",
  "lat":"51.5073219",
  "lon":"-0.1276474",
  "display_name":"London, Greater London, England, United Kingdom",
  "class":"place",
  "type":"city",
  "importance":0.9754895765402
},
{
  "place_id":"4566287",
  "osm_type":"node",
  "osm_id":"485248691",
  "lat":"42.988097",
  "lon":"-81.2460295",
  "display_name":"London, Ontario, Canada",
  "class":"place",
  "type":"city",
  "importance":0.6515723047601
}

(just a sample of how data is stored in my db)

Community
  • 1
  • 1
Tony Roczz
  • 2,366
  • 6
  • 32
  • 59
  • When asking questions of and using MongoDB to store such data the n you really should read the documentation. To find things "near" a point given another, then just use [**`$nearSphere`**](http://docs.mongodb.org/manual/reference/operator/query/nearSphere/) for geographic locations. Learn about that an geospatial indexes. And/Or show us how you have stored the data. – Blakes Seven Aug 07 '15 at 09:15
  • @BlakesSeven I have added a sample of how data is stored in my db and am going through the geospatial indexes and documentation – Tony Roczz Aug 07 '15 at 09:42

1 Answers1

2

The very "first" thing you must do is change how you are storing your data if you intend to use geospatial queries with MongoDB. You have the option of legacy coordinate pairs or GeoJSON format. But your current storage with "lat" and "long" in separate fields and also as "strings" will not work.

Here is a schema fix for your collection, written for the mongo shell because this should be a one off operation. I'm advising on GeoJSON, as it is generally compatible with quite a few libraries, and all distances returned are in kilometers rather than radians.

var bulk = db.collection.initializeUnorderedBulkOp(),
    count = 0;

db.collection.find().forEach(function(doc) {
   bulk.find({ "_id": doc._id }).updateOne({
       "$set": {
           "location": {
               "type": "Point",
               "coordinates": [parseFloat(doc.lon),parseFloat(doc.lat)]
           }        
       },
       "$unset": { "lat": "", "lon": "" }
   });
   count++;

   if ( count % 1000 == 0 ) {
       bulk.execute();
       bulk = db.collection.initializeUnorderedBulkOp();
   }
});

if ( count % 1000 !=0 )
   bulk.execute();

Now the data is fixed and compatible with an index, create the index. What makes sense here with GeoJSON data is a "2sphere" index:

db.collection.createIndex({ "location": "2dsphere" })

Now you are ready to query. Sticking with the shell as the python syntax is identical and I don't know your library calls:

db.collection.find({
    "location": {
        "$nearSphere": {
            "$geometry": {
                "type": "Point",
                "coordinates": [lon,lat]
            },
            "$maxDistance": distance
        }
    }
})

This query uses $nearSphere which will calculate properly on distance based on the curvature of the earth, ideal for real location data. Your three variables there are the "longitude", "latitude" ( in that order ) in the coordinates array and the "distance" under $maxDistance that you want to find things within that radius.

This is a very simple query procedure once your data is suitable and the required geospatial index is in place.

No need for messy calculations in your client, as the server does all the work.

The links to the relevant documentation parts are all included for your reference. Read them and learn more about geospatial queries with MongoDB.

Blakes Seven
  • 49,422
  • 14
  • 129
  • 135
  • Is the index automatically created or I have to create the index and store as new collection – Tony Roczz Aug 07 '15 at 10:54
  • @TonyRoczz No indexes are "automatically" created. There is an example in the listing of how to create and also a link to the documentation. I am honestly emploring you to spend more time reading the MongoDB documentation if you aer going to continue to work with it. Most of your recent questions are generally solved by reading the documentation as it is. Your questions could be also more to the point for reading the documentation and posting questions specifically about the parts you do not understand or have problems implementing when implementing your code. – Blakes Seven Aug 07 '15 at 11:04
  • The thing is that initially I wanted to do a mathematical calculation on how to find the bounding box. The user will give the location as a string `"London, Ontario, Canada"` , then I will get the "lat and long" value from db and do the calculation and get the result with the help of `geopy` module. I did not think of doing everything within the database since only selected locations are stored inside the collection – Tony Roczz Aug 07 '15 at 13:14
  • @TonyRoczz To clarify here my own experience in reading your questions covers these topics. 1. "How to write JSON data as strings from python?" When there are basic methods to actually serialize from data structures. 2. "How to aggregate and combine data to python dicts?". When all you needed to do was call the `aggregate()` method of MongoDB. Now, 3. "Calculate distances from location data with python?". When again all you need to do is use the database features. There is nothing hard in this. Forget the "bounding box" and look at what you are **really** asking. Just as I have several times. – Blakes Seven Aug 07 '15 at 13:21
  • @TonyRoczz I just want to add as it's near time for me to retire for my night, that like on all other occasions here I am only trying to help you understand how to do things better. Believe me, this answer here is for no others benefit other than yourself. The basic premise has been answered before and this will surely eventually close and go away. Learn the lessons of how to use the correct tools for the job at hand and become a better programmer. Kira, out. – Blakes Seven Aug 07 '15 at 14:32
  • I have small issue the code which you gave for converting my data to GeoJSON format is not working. I tried to figure it but with no luck. sorry am just a beginner, I will surely work hard and learn more to become a better programmer. – Tony Roczz Aug 08 '15 at 09:59
  • @TonyRoczz Yes there were some typing mistakes in there that I have now corrected. I have also run this against the sample provided by yourself and it runs perfectly. Understand that "collection" here means to be replaced with your 'actual' collection name. – Blakes Seven Aug 08 '15 at 10:21
  • my collection holds around 50000 records will convert every single record. I just tried it and it reported some error. But viewed my collection and the records were altered in the first few screens, I am asking this because of the error. – Tony Roczz Aug 08 '15 at 10:46
  • @TonyRoczz The operations work perfectly on what you have presented. This is what an asnwer does. If this leads to to additional questions for things that you cannot work out yourself, then you post other questions. I cannot sit here a debug your own operations remotely without you placing that detail into another question. Not this one. It is answered. – Blakes Seven Aug 08 '15 at 11:08