Cro*_*sey 9 python postgis sqlalchemy shapely geoalchemy
我有一个应用程序,它接收一个地址字符串,将其发送到谷歌地图API并获得纬度/经度坐标,然后我想显示这一点的X meteres内的所有用户(lat/long存储在我的数据库中) ,然后我想过滤结果只显示某些宠物的用户
首先,我有我的模特
class User(UserMixin, Base):
first_name = Column(Unicode)
address = Column(Unicode)
location = Column(Geometry('POINT'))
pets = relationship('Pet', secondary=user_pets, backref='pets')
class Pet(Base):
__tablename__ = 'pets'
id = Column(Integer, primary_key=True)
name = Column(Unicode)
user_pets = Table('user_pets', Base.metadata,
Column('user_id', Integer, ForeignKey('users.id')),
Column('pet_id', Integer, ForeignKey('pets.id'))
)
Run Code Online (Sandbox Code Playgroud)
我从谷歌API获取我的lat/long并将其存储在我的数据库中,所以从地址字符串"伦敦英格兰"我得到
POINT (-0.1198244000000000 51.5112138999999871)
Run Code Online (Sandbox Code Playgroud)
这存储在我的数据库中,如:
0101000000544843D7CFACBEBF5AE102756FC14940
Run Code Online (Sandbox Code Playgroud)
现在一切正常,现在阅读Geoalchemy2文档,我似乎无法找到解决我的问题的exmaple查询.
我想传递的是Geoalchemy2的另一组lat/long坐标,然后返回最近的10个用户.在查询这个问题的同时,我也只会过滤那些有某些宠物的用户(这对我的查询起作用并不重要,但我想展示查询实际上会做什么).
我不想在没有提供示例查询的情况下回答问题,但我真的不知道应该使用哪些函数来实现我所需的结果.
我猜我需要使用"ST_DWithin"或"ST_DFullyWithin",但我找不到任何一个函数的完整示例.谢谢.
所以我知道有一个有效的查询
distance = 10
address_string = "London, England"
results = Geocoder.geocode(address_string)
# load long[1], lat[0] into shapely
center_point = Point(results.coordinates[1], results.coordinates[0])
print center_point
# 'POINT (-0.1198244000000000 51.5112138999999871)'
wkb_element = from_shape(center_point)
users = DBSession.query(User).\
filter(func.ST_DWithin(User.location, wkb_element, distance)).all()
Run Code Online (Sandbox Code Playgroud)
其中生成以下SQL
2013-12-30 15:12:06,445 INFO [sqlalchemy.engine.base.Engine][Dummy-2] SELECT users.first_name AS users_first_name, users.last_name AS users_last_name, users.phone AS users_phone, users.address AS users_address, users.about AS users_about, ST_AsBinary(users.location) AS users_location, users.profile_image_id AS users_profile_image_id, users.searchable AS users_searchable, users.user_password AS users_user_password, users.registered_date AS users_registered_date, users.id AS users_id, users.last_login_date AS users_last_login_date, users.status AS users_status, users.user_name AS users_user_name, users.email AS users_email, users.security_code AS users_security_code
FROM users
WHERE ST_DWithin(users.location, ST_GeomFromWKB(%(ST_GeomFromWKB_1)s, %(ST_GeomFromWKB_2)s), %(param_1)s)
2013-12-30 15:12:06,445 INFO [sqlalchemy.engine.base.Engine][Dummy-2] {'ST_GeomFromWKB_1': <read-only buffer for 0x7f7d10258f70, size -1, offset 0 at 0x7f7d10258db0>, 'param_1': 10, 'ST_GeomFromWKB_2': -1}
Run Code Online (Sandbox Code Playgroud)
现在这总是返回我的所有用户,无论距离变量如何,所以我猜测某些事情并不完全正确,但我无法解决原因.
回答:
单位是半径,所以我不得不将里程转换为degress以获得最佳(粗略)估计.它不需要准确:
d = 90
distance = d * 0.014472
#1 mile = 0.014472 degrees
r1 = -0.1198244
r2 = 51.5112139
# load long[1], lat[0] into shapely
center_point = Point(r1, r2)
# 'POINT (-0.1198244000000000 51.5112138999999871)'
wkb_element = from_shape(center_point)
users = DBSession.query(User).\
filter(func.ST_DFullyWithin(User.location, wkb_element, distance)).all()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1648 次 |
| 最近记录: |