【问题标题】:Geoalchemy2 & ST_Within - type mismatch between point and polygon?Geoalchemy2 & ST_Within - 点和多边形之间的类型不匹配?
【发布时间】:2017-06-25 15:59:50
【问题描述】:

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

这是失败的查询:

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(geography, geometry) 不存在 第 3 行:在哪里 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 和
  • 地球炼金术2 0.4.0

【问题讨论】:

    标签: python postgresql sqlalchemy postgis geoalchemy2


    【解决方案1】:

    感谢其他人(Mike Bayer 和 Greg Baker)的帮助,我可以发布答案。

    问题是:

    1. 我的点是 Geography 类型,我的多边形是 Geometry 类型,并且
    2. 许多其他 PostGIS 函数,包括 ST_Within,不支持地理(即它们仅支持几何)。

    答案是在查询中将 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))')))
    

    【讨论】:

      【解决方案2】:

      如果你愿意

      返回位于矩形内的每个点,其中点和矩形基于真实世界的经度和纬度

      使用geography 数据类型,您可以使用ST_IntersectsST_Covers,因为它们支持geography 数据类型并给出更准确的结果。

      PostGIS documentation: "地理上的函数(面积、距离、长度、交叉点等)是使用球体上的弧计算的。通过考虑世界的球体形状,这些函数可以提供更准确的结果.

      另一方面,他们“需要更多的 CPU 时间来执行”[1]

      PostGIS Geography Support Functions的列表

      【讨论】:

        猜你喜欢
        • 2022-01-03
        • 2017-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多