我有一个应用程序,它接受一个地址字符串,将它发送到Google并得到lat/long协调,然后我想显示这一点的X米范围内的所有用户( 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'))
)我从Google获得lat/long,并将它存储在我的数据库中,所以我从地址字符串"London England“中得到
POINT (-0.1198244000000000 51.5112138999999871)它存储在我的数据库中,类似于:
0101000000544843D7CFACBEBF5AE102756FC14940现在一切都很好,现在阅读Geoalchemy2文档,我似乎找不到一个解决问题的示例查询。
我想传递的是另一组lat/long协调器到Geoalchemy2,然后返回最接近的用户,比如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()生成以下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}现在,它总是返回我所有的用户,不管是什么距离变量,所以我猜有些东西不是完全正确的,但是我不知道为什么。
发布于 2013-12-30 16:11:58
答案:
单位是在一个度半径,所以我不得不转换英里,以得到最好的(粗略)估计。它不需要精确:
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()发布于 2014-01-05 16:39:43
Lat/Lon数据并不特别适合于距离计算。
每一纬度相距约69英里(111公里)。范围因地球的略椭圆形而变化,从赤道的68.703英里(110.567公里)到两极的69.407英里(111.699公里)不等。这很方便,因为每分钟(1/60度)大约是一英里。
在69.172英里(111.321英里)的赤道处,经度是最宽的,在两极逐渐缩小到零。在北纬40度或南纬40度处,经度之间的距离为53英里(85公里)。
您可以使用转换将坐标转换为使用米或英里的不同投影。它们往往是局部的,因为它们将地球的球体投射到一个光栅化的平面上。英国国家电网(SRID 27700)可能适合您的需要。
https://stackoverflow.com/questions/20803878
复制相似问题