首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python - SqlAlchemy:按大圆距离过滤查询?

Python - SqlAlchemy:按大圆距离过滤查询?
EN

Stack Overflow用户
提问于 2011-09-29 17:14:43
回答 3查看 2.1K关注 0票数 2

我使用Python和Sqlalchemy在Sqlite数据库中存储纬度和经度值。我已经为我的Location对象创建了一个hybrid method

代码语言:javascript
复制
@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

所有像cos_rad_latsin_rad_lat这样的值都是我为优化计算而预先计算的值。无论如何,当我运行以下查询时,

代码语言:javascript
复制
pq = Session.query(model.Location).filter(model.Location.great_circle_distance(loc) < 10)

我得到以下错误,

代码语言:javascript
复制
line 809, in great_circle_distance
    * math.cos(self.rad_lng - other.rad_lng)
TypeError: a float is required

例如,当我打印self.rad_lngother.rad_lng的值时,

代码语言:javascript
复制
self.rad_lng: Location.rad_lng 
other.rad_lng: -1.29154947064

我做错了什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-29 23:37:58

您不能真正以这种方式使用math模块:

代码语言:javascript
复制
>>> 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

您将在@great_circle_distance.expression method中组合sqalchemy.func.*而不是math.*,以实现所有这类智能。不幸的是,使用sqlite也不能做到这一点;你可以使用PostgreSQL来doesn't provide trig functions,或者你可以尝试add these functions to sqlite yourself:

编辑向sqlite添加函数实际上并不难:这是未经测试的。

我必须将数学函数添加到sqlite:

代码语言:javascript
复制
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
票数 7
EN

Stack Overflow用户

发布于 2011-09-29 18:23:13

显然,你不能从这个字符串中得到一个浮点数。

这是因为您使用的是"self",作为调用的第一个参数,它表明该方法是对象的一部分,而不是您可能传递的某个变量。

你应该试试这个:

代码语言:javascript
复制
def great_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

我假设上面的全局变量"self.cos_rad_lat“和"self.sin_rad_lat”是在程序中的其他地方用正确的值初始化的,可能是在同一对象的"init“部分。

票数 0
EN

Stack Overflow用户

发布于 2011-09-29 18:29:22

看起来你做的每件事都是正确的,但不知何故,这个方法并没有真正“混合”起来。你会不会做了一些愚蠢的事情,比如在你的源代码中没有真正的放置装饰器?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7595050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档