Python-SqlAlchemy : Filter query by great circle distance?

标签 python database sqlite sqlalchemy pylons

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

@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 等所有值都是我预先计算的值,以优化计算。无论如何,当我运行以下查询时,

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

我得到以下错误,

line 809, in great_circle_distance
    * math.cos(self.rad_lng - other.rad_lng)
TypeError: a float is required

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

self.rad_lng: Location.rad_lng 
other.rad_lng: -1.29154947064

我做错了什么?

最佳答案

你不能真的那样使用 math 模块:

>>> 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 做到这一点;它doesn't provide trig functions 您可以使用 PostgreSQL,它可以,或者您可以尝试 add these functions to sqlite yourself:

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

必须将数学函数添加到 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

关于Python-SqlAlchemy : Filter query by great circle distance?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7595050/

相关文章:

python - ElasticSearch 在索引整数和字符串的 JSON 数组时抛出映射器解析异常

python - python中Queue.Queue()实例的转换

sql - 查询太复杂?使用追加查询

mysql - 显示两个表的输出,但通过第三个表匹配它们

mysql - 对 MySQL 中获取锁的方式进行排序

python - 通过使用值计数拆分来比较 pandas 字符串

Python 处理文件中的行时出错

android - SQLite:如何获取长类型值的平均值

sqlite - 更新时创建 Sqlite 数据库补丁

performance - 为什么 SQLite 3.7.2 在 Step 操作上比 3.7.9 快 3 倍