I’m using sqlAlchemy ORM and would like to like to calculate and return the distance from a given point and the stored points.
class Event(Base):
__tablename__ = 'events'
# Schema
id = Column(Integer, primary_key=True)
title = Column(String(150))
description = Column(Text)
url = Column(String(800))
lat = Column(Float)
lng = Column(Float)
….and my query:
nearest = """SELECT *, ((lat - '-41.288889') * (lat - '-41.288889')
+ (lng - 174.777222) * (lng - 174.777222)) AS distance FROM events
ORDER BY distance ASC """
e = Event.query.from_statement(nearest)
This of seems to return the objects in the correct order, but I have no access to the distance attribute. How do I access this value – or what is the best-practice way of accomplishing this?
Problem 1: Latitude degrees and longitude degrees have different lengths … same at the equator (assuming earth is a sphere) but at the poles a longitude degree has zero length.
Update To give an example of the severity of your problem:
Travelling north or south by one degree of latitude will cover about 111.2 km (assuming that the earth is a sphere). Travelling east or west by one degree of longitude will cover about 111.2 km at the equator. At a latitude of -41.3 degrees, it will cover only 83.5 km.
From (-41.3, 174.8) due east to (-41.3, 174.92) is 10.0 km. Your calculation treats it as though it is 13.3 km away — an error of 33%.
You can get to within a 4 metre error by a fairly simple approximation:
This approximate distance is good enough for “find the nearest pizza shop” applications, and has the advantage that it can be used in bare-bones environments like SQLite which don’t support sin/cos/tan and their inverses out of the box.
Problem 2: SQLite is tolerant, but you shouldn’t make a habit of using quotes as in
(lat - '-41.288889')Problem 3: I can’t reproduce your problem at the SQLlite level:
Perhaps you should elaborate on “This of seems to return the objects in the correct order, but I have no access to the distance attribute” … what does introspecting
etell you?