我想运行一个查询,返回矩形内的每个点,其中点和矩形基于真实世界的经度和纬度。
这是一个失败的查询:
results = session.query(Store.id).filter(func.ST_Within(Store.location, func.ST_GeomFromEWKT('SRID=4326;POLYGON((150 -33, 152 -33, 152 -31, 150 -31, 150 -33))')))
它运行时没有抱怨,但当调用results.first()时,我看到以下错误和警告:
sqlalchemy.exc.ProgramingError:(psycopg2.ProgrammingError)函数st_wwithin(地理、几何)不存在第3行:其中ST_Wwithin(store.location,ST_GeomFromEWKT('SRID=4326;P。。。^提示:没有任何函数与给定的名称和参数类型匹配。您可能需要添加显式类型强制转换。[SQL:'SELECT store.id AS store_id \nFROM store\n此处ST_Wwithin(store.location,ST_GeomFromEWKT(%(ST_Geom FromEWKT_1)s))\n LIMIT%(param_1)s'][参数:{'ST_GeomFromEWKT_1':'SRID=4326;POLYGON((150-33,152-33,152-3150-31150-33))','param_1':1}]
然而,我可以通过在查询中创建一个伪点(这会使每个存储都匹配)来使查询工作:
results = session.query(Store.id).filter(func.ST_Within(func.ST_GeomFromEWKT('SRID=4326;POINT(151 -32)'), func.ST_GeomFromEWKT('SRID=4326;POLYGON((150 -33, 152 -33, 152 -31, 150 -31, 150 -33))')))
这表明问题出在我的Store.location字段上,但我尝试过的[包括type_coerce(Store.location,Geography)]都不起作用。
这是我对location列的SQLAlchemy定义:
location = Column(Geography(geometry_type='POINT', srid=4326))
这是我运行的代码;纬度到一个位置(我也尝试过使用func.ST_GeomFromEWKT()强制类型):
stores = session.query(Store)
for store in stores:
store.location = 'SRID=4326;POINT({} {})'.format(store.longitude, store.latitude)
session.commit()
Python告诉我Store.location的类型是"geoalchemy2.elements.WKBElement",这正是我从文档中所期望的。
有人对如何解决这个问题有什么建议吗?
仅供参考我正在运行:
- PostgreSQL 9.6.1
- psycopg2 2.6.2
- SQLAlchemy 1.1.4,以及
- 地球化学2 0.4.0
感谢其他人(Mike Bayer和Greg Baker)的帮助,我可以发布答案。
问题是:
- 我的点是Geography类型,多边形是Geometry类型,并且
- 许多其他PostGIS功能,包括ST_Wwithin,不支持地理(即,它们只支持几何图形)
答案是将Geography转换为查询中的Geometry。以下查询有效:
results = session.query(Store.id).filter(func.ST_Within(cast(Store.location, Geometry), func.ST_GeomFromEWKT('SRID=4326;POLYGON((150 -33, 152 -33, 152 -31, 150 -31, 150 -33))')))
如果您想
返回矩形内的每个点,其中点和矩形基于真实世界的经度和纬度
使用geography
数据类型时,可以使用ST_Intercepts和ST_Covers,因为它们支持geography
数据类型并提供更准确的结果。
PostGIS文档:地理上的函数(面积、距离、长度、交点等)是使用球体上的圆弧计算的。通过将世界的球体形状考虑在内,函数可以提供更准确的结果";
另一方面,他们">需要更多的CPU时间来执行";[1]
PostGIS地理支持功能列表