GeoAlchemy2:找到一组不与单独集相交的几何项

时间:2014-03-09 19:54:38

标签: python postgis geoalchemy

我有一个名为tasks的postgis数据库表,使用geoalchemy2 / sqlalchemy映射到python类Task - 每个条目都有一个MultiPolygon geometry和一个整数state。总的来说,我的数据库中的条目涵盖了一个地理区域。我想选择state = 0的随机条目,该条目在地理上不与state = 1 的任何条目相邻。

这是选择state = 0的随机条目的代码:

class Task(Base):
    __tablename__ = "tasks"
    id = Column(Integer, primary_key=True, index=True)
    geometry = Column(Geometry('MultiPolygon', srid=4326))
    state = Column(Integer, default=0)

session = DBSession()
taskgetter = session.query(Task).filter_by(state=0)
count = taskgetter.count()
if count != 0:
    atask = taskgetter.offset(random.randint(0, count-1)).first()

到目前为止一切顺利。但现在,如何确保它们不与另一组条目相邻?

Geoalchemy有一个函数ST_Union可以统一几何,而ST_Disjoint可以检测它们是否相交。所以似乎我应该能够选择状态= 1的项目,将它们合并为一个几何体,然后过滤掉我的原始查询(上面)以仅保留与它不相交的项目。但我找不到在地质考试中表达这种方法的方法。这是我试过的一种方式:

session = DBSession()
taskgetter = session.query(Task).filter_by(state=0) \
    .filter(Task.geometry.ST_Disjoint(session.query( \
            Task.geometry.ST_Union()).filter_by(state=1)))
count = taskgetter.count()
if count != 0:
    atask = taskgetter.offset(random.randint(0, count-1)).first()

并产生如下错误:

ProgrammingError: (ProgrammingError) subquery in FROM must have an alias
LINE 3: FROM tasks, (SELECT ST_Union(tasks.geometry) AS "ST_Union_1"...
                    ^
HINT:  For example, FROM (SELECT ...) [AS] foo.
 'SELECT count(*) AS count_1 
FROM (SELECT tasks.id AS tasks_id
FROM tasks, (SELECT ST_Union(tasks.geometry) AS "ST_Union_1" 
FROM tasks 
WHERE tasks.state = %(state_1)s) 
WHERE tasks.state = %(state_2)s AND ST_Disjoint(tasks.geometry, (SELECT ST_Union(tasks.geometry) AS "ST_Union_1" 
FROM tasks 
WHERE tasks.state = %(state_1)s))) AS anon_1' {'state_1': 1, 'state_2': 0}

1 个答案:

答案 0 :(得分:1)

在黑暗中拍摄,因为我没有设置来测试它:

这似乎与SQLAlchemy的子查询相关,而不是GeoAlchemy,尝试在子查询的末尾添加.subquery()来生成别名(cf:http://docs.sqlalchemy.org/en/rel_0_9/orm/tutorial.html#using-subqueries

编辑: 仍然使用链接教程中的信息,我认为这可能有效:

state1 = session.query(
        Task.geometry.ST_Union().label('taskunion')
        ).filter_by(state=1).subquery()

taskgetter = session.query(Task)\
        .filter_by(state=0)
        .filter(Task.geometry.ST_Disjoint(state1.c.taskunion))

在您在子查询上创建的列中添加标签,以便在超级查询中引用它。