首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Geoalchemy2查询X米内的所有用户

Geoalchemy2查询X米内的所有用户
EN

Stack Overflow用户
提问于 2013-12-27 16:12:46
回答 2查看 2.4K关注 0票数 9

我有一个应用程序,它接受一个地址字符串,将它发送到Google并得到lat/long协调,然后我想显示这一点的X米范围内的所有用户( lat/long存储在我的数据库中),然后我想过滤结果,只显示用户与特定宠物。

所以首先,我有我的模特

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

代码语言:javascript
复制
POINT (-0.1198244000000000 51.5112138999999871)

它存储在我的数据库中,类似于:

代码语言:javascript
复制
0101000000544843D7CFACBEBF5AE102756FC14940

现在一切都很好,现在阅读Geoalchemy2文档,我似乎找不到一个解决问题的示例查询。

我想传递的是另一组lat/long协调器到Geoalchemy2,然后返回最接近的用户,比如10个用户。在查询时,我还将只过滤有特定宠物的用户(这对我的查询工作来说并不重要,但我想展示查询的全部功能)。

我真的不喜欢在没有提供示例查询的情况下回答问题,但是我真的不知道我应该使用什么函数来实现我所需的结果。

我猜我需要使用"ST_DWithin“或"ST_DFullyWithin”,但我找不到这两个函数的完整示例。谢谢。

所以我知道有一个有用的查询

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

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

现在,它总是返回我所有的用户,不管是什么距离变量,所以我猜有些东西不是完全正确的,但是我不知道为什么。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-12-30 16:11:58

答案:

单位是在一个度半径,所以我不得不转换英里,以得到最好的(粗略)估计。它不需要精确:

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

Stack Overflow用户

发布于 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)可能适合您的需要。

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

https://stackoverflow.com/questions/20803878

复制
相关文章

相似问题

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