python过滤sql_Python-SqlAlchemy:通过大圆距过滤查询?

I am using Python and Sqlalchemy to store latitude and longitude values in a Sqlite database. I have created a hybrid method for my Location object,

@hybrid_method

def great_circle_distance(self, other):

"""

Tries to calculate the great circle distance between the two locations

If it succeeds, it will return the great-circle distance

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

All the values like cos_rad_lat and sin_rad_lat are values I pre-calculated to optimize the calculation. Anyhow, when I run the following query,

pq = Session.query(model.Location).filter(model.Location.great_circle_distance(loc) < 10)

I get the following error,

line 809, in great_circle_distance

* math.cos(self.rad_lng - other.rad_lng)

TypeError: a float is required

When I print the values for self.rad_lng and other.rad_lng I get, for example,

self.rad_lng: Location.rad_lng

other.rad_lng: -1.29154947064

What am I doing wrong?

解决方案

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 "", line 1, in

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)

class Location(...):

...

@hybrid_method

def great_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.expression

def great_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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值