1

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

这是选择 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可以检测它们是否相交。所以看来我应该能够选择 state=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}
4

1 回答 1

1

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

这似乎与 SQLAlchemy 的子查询有关,而不是 GeoAlchemy,尝试在子查询末尾添加 .subquery() 以生成别名(参见: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))

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

于 2014-03-09T20:24:16.400 回答