Python - Sqlalchemy: Filter Query By Great Circle Distance?
Solution 1:
You can't really use the math
module that way:
>>>c = toyschema.Contact()>>>c.lat = 10>>>c.lat
10
>>>import math>>>math.cos(c.lat)
-0.83907152907645244
>>>math.cos(toyschema.Contact.lat)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: a float is required
You'll have combine sqalchemy.func.*
in place of math.*
in a @great_circle_distance.expression
method for all of that kind of cleverness. Unfortunately, you can't do that with sqlite, either; it doesn't provide trig functions
You could use PostgreSQL, which does, or you can try to add these functions to sqlite yourself:
EDIT It's actually not to hard to add functions to sqlite: This is NOT tested.
Have to add the math functions to sqlite:
engine = sqlalchemy.create_engine("sqlite:///:memory:/")
raw_con = engine.raw_connection()
raw_con.create_function("cos", 1, math.cos)
raw_con.create_function("acos", 1, math.acos)
classLocation(...):
...
@hybrid_methoddefgreat_circle_distance(self, other):
"""
Tries to calculate the great circle distance between
the two locations by using the Haversine formula.
If it succeeds, it will return the Haversine formula
multiplied by 3959, which calculates the distance in miles.
If it cannot, it will return None.
"""return math.acos( self.cos_rad_lat
* other.cos_rad_lat
* math.cos(self.rad_lng - other.rad_lng)
+ self.sin_rad_lat
* other.sin_rad_lat
) * 3959 @great_circle_distance.expressiondefgreat_circle_distance(cls, other):
return sqlalchemy.func.acos( cls.cos_rad_lat
* other.cos_rad_lat
* sqlalchemy.func.cos(cls.rad_lng - other.rad_lng)
+ cls.sin_rad_lat
* other.sin_rad_lat
) * 3959
Solution 2:
Obviously, you cannot get a float from that string.
It is because you are using "self", which, as first parameter of the call, indicates that the method is a part of the object, and not some var you may pass on.
You should try this :
defgreat_circle_distance(self, first, other):
"""
Tries to calculate the great circle distance between
the two locations by using the Haversine formula.
If it succeeds, it will return the Haversine formula
multiplied by 3959, which calculates the distance in miles.
If it cannot, it will return None.
"""return math.acos( self.cos_rad_lat
* other.cos_rad_lat
* math.cos(first.rad_lng - other.rad_lng)
+ self.sin_rad_lat
* other.sin_rad_lat
) * 3959
I suppose here above that the global variables "self.cos_rad_lat" and "self.sin_rad_lat" are initiated with correct values somewhere else in your program, probably in the "init" section of the same object.
Solution 3:
It does look like you've done everything correctly, but somehow the method is not actually getting 'hybridized'. Could you have done something stupid, like not actually put the decorator on in your source code?
Post a Comment for "Python - Sqlalchemy: Filter Query By Great Circle Distance?"