Sqlalchemy/Geoalchemy2实现MariaDB半径搜索返回空列表问题
解决MariaDB半径搜索返回空列表的问题
核心问题分析
你的代码用Python f-string拼接SQL表达式时,会把models.Location.lng和models.Location.lat直接转成Python对象的字符串形式,而非SQL表的列名引用,导致生成的SQL完全错误,自然查不到数据。另外,MariaDB的ST_Distance_Sphere返回单位是米,如果你的radius参数是公里数,需要先转成米(乘以1000),否则会把公里当成米判断,范围缩小1000倍,也可能返回空。
修正后的代码
from sqlalchemy import func from sqlalchemy.orm import Session def get_locations_in_radius(db: Session, radius: int, lat: float, lng: float): # 把公里转为米(若radius以公里为单位) radius_meters = radius * 1000 locations = db.query(models.Location).filter( func.ST_Distance_Sphere( # 用SQL函数构建点,直接引用列,避免f-string拼接错误 func.ST_Point(models.Location.lng, models.Location.lat), func.ST_Point(lng, lat) ) <= radius_meters ).all() return locations
额外检查项
- 确认数据库中
lat和lng的存储顺序:确保models.Location.lng是经度、models.Location.lat是纬度,和ST_Point的参数顺序(经度在前、纬度在后)一致。 - 可打印生成的SQL验证正确性:
查看输出的SQL是否正确引用了列名,而非Python对象的字符串。query = db.query(models.Location).filter(...) print(query.statement) - 若MariaDB版本低于10.2.5,
ST_Distance_Sphere可能不支持直接用ST_Point,可改用SQL表达式拼接WKT:func.ST_GeomFromText(func.concat('POINT(', models.Location.lng, ' ', models.Location.lat, ')'))
内容的提问来源于stack exchange,提问作者RottenSchnitzel
相关产品推荐
相关产品推荐

