Using GeopositionField to find closest database entries
django, django-geoposition, geocoding, geolocation, python
Solution
For the distance between two points you can use Geopy.
From the documetation: Here's an example usage of distance.distance:
>>> from geopy import distance
>>> _, ne = g.geocode('Newport, RI')
>>> _, cl = g.geocode('Cleveland, OH')
>>> distance.distance(ne, cl).miles
538.37173614757057
To implement this in a Django project. Create a normal model in models.py:
class User(models.Model):
name = models.Charfield()
lat = models.FloatField()
lng = models.FloatField()
To optimize a bit you can filter user objects to get a rough estimate of nearby users first. This way you don't have to loop over all the users in the db. This rough estimate is optional. To meet all your project requirements you maybe have to write some extra logic:
#The location of your user.
lat, lng = 41.512107999999998, -81.607044999999999
min_lat = lat - 1 # You have to calculate this offsets based on the user location.
max_lat = lat + 1 # Because the distance of one degree varies over the planet.
min_lng = lng - 1
max_lng = lng + 1
users = User.objects.filter(lat__gt=min_lat, lat__lt=max__lat, lat__gt=min_lat, lat__lt=max__lat)
# If not 20 fall back to all users.
if users.count() <= 20:
users = User.objects.all()
Calculate the distance between your user and each user in users, sort them by distance and get the first 20.
results = []
for user in users:
d = distance.distance((lat, lng), (user.lat, user.lng))
results.append( {'distance':d, 'user':user })
results = sorted(results, key=lambda k: k['distance'])
results = results[:20]
Problem
I am using GeopositionField in Django to store the coordinates of my user. Now I want to find a list of 20 users who are closest to current user. Can that functionality be acheaved my GeopositionField? I know that GeoDjango makes it easy to search distances, but since I am using Heroku and postgresql, I want to keep the costs down and with postgressql, installing PostGIS seems to be the only alternative. Any suggestions?