Geoalchemy2& ST_Within - 点和多边形之间的类型不匹配?

时间:2017-02-08 06:36:21

标签: python postgresql sqlalchemy postgis geoalchemy2

我想运行一个查询,它返回一个落在矩形内的每个点,其中点和矩形基于真实世界的经度和纬度。

这是失败的查询:

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.ProgrammingError:(psycopg2.ProgrammingError)函数st_within(地理,几何)不存在   第3行:WHERE ST_Within(store.location,ST_GeomFromEWKT(' SRID = 4326; P ...                 ^   提示:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。    [SQL:' SELECT store.id AS store_id \ nFROM store \ nWHERE ST_Within(store.location,ST_GeomFromEWKT(%(ST_GeomFromEWKT_1)s   ))\ n LIMIT%(param_1)s'] [参数:{' ST_GeomFromEWKT_1':' SRID = 4326; POLYGON((150 -33,152 -33,152 -31, 150 -31,150    -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,Geoography)]。

这是我对位置列的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和
  • Geoalchemy2 0.4.0

1 个答案:

答案 0 :(得分:1)

感谢其他地方的帮助(Mike Bayer和Greg Baker),我可以发一个答案。

问题在于:

  1. 我的观点是Geography类型,我的多边形是Geometry类型,
  2. 许多其他PostGIS功能(包括ST_Within)不支持地理位置(即它们仅支持几何图形)。
  3. 答案是在查询中将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))')))