SpatiaLite教程¶
GeoAlchemy 2的主要目标是PostGIS。但GeoAlchemy 2也支持SpatiaLite,即SQLite的空间扩展。本教程介绍如何将GeoAlchemy 2与SpatiaLite结合使用。它基于 ORM教程 ,你可能想先读一下。
连接到数据库¶
就像使用PostGIS连接到空间数据库时需要 Engine
. 这就是你如何为SpatiaLite创建一个:
>>> from sqlalchemy import create_engine
>>> from sqlalchemy.event import listen
>>>
>>> def load_spatialite(dbapi_conn, connection_record):
... dbapi_conn.enable_load_extension(True)
... dbapi_conn.load_extension('/usr/lib/x86_64-linux-gnu/mod_spatialite.so')
...
>>>
>>> engine = create_engine('sqlite:///gis.db', echo=True)
>>> listen(engine, 'connect', load_spatialite)
呼唤 create_engine
创建绑定到数据库文件的引擎 gis.db
. 在那之后 connect
侦听器已在引擎上注册。侦听器负责加载SpatiaLite扩展,这是通过SQL使用SpatiaLite的必要操作。
此时,您可以测试是否能够连接到数据库:
>> conn = engine.connect()
2018-05-30 17:12:02,675 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2018-05-30 17:12:02,676 INFO sqlalchemy.engine.base.Engine ()
2018-05-30 17:12:02,676 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2018-05-30 17:12:02,676 INFO sqlalchemy.engine.base.Engine ()
你也可以检查 gis.db
在文件系统上创建了SQLite数据库文件。
使用SpatiaLite还需要另外一个步骤:创建 geometry_columns
和 spatial_ref_sys
元数据表。这是通过调用SpatiaLite的 InitSpatialMetaData
功能:
>>> from sqlalchemy.sql import select, func
>>>
>>> conn.execute(select([func.InitSpatialMetaData()]))
请注意,第一次对数据库执行此操作可能需要一些时间。什么时候? InitSpatialMetaData
再次执行时将报告错误:
InitSpatiaMetaData() error:"table spatial_ref_sys already exists"
你可以放心地忽略这个错误。
在继续之前,我们可以关闭当前连接:
>>> conn.close()
声明映射¶
现在我们有了一个工作连接,我们可以继续创建Python类和数据库表之间的映射。
>>> from sqlalchemy.ext.declarative import declarative_base
>>> from sqlalchemy import Column, Integer, String
>>> from geoalchemy2 import Geometry
>>>
>>> Base = declarative_base()
>>>
>>> class Lake(Base):
... __tablename__ = 'lake'
... id = Column(Integer, primary_key=True)
... name = Column(String)
... geom = Column(Geometry(geometry_type='POLYGON', management=True))
这基本上和PostGIS一样有效。不同的是 management
必须设置为的参数 True
.
设置 management
到 True
表示 AddGeometryColumn
和 DiscardGeometryColumn
管理功能将用于创建和删除几何列。这在空间上是必需的。
在数据库中创建表¶
我们现在可以创建 lake
中的表 gis.db
数据库:
>>> Lake.__table__.create(engine)
如果我们想放下我们要用的桌子:
>>> Lake.__table__.drop(engine)
这里没有什么特殊的空间。
创建会话¶
当使用SQLAlchemy ORM时,ORM通过 Session
.
>>> from sqlalchemy.orm import sessionmaker
>>> Session = sessionmaker(bind=engine)
>>> session = Session()
会议与我们的空间有关 Engine
. 再说一次,这里没有任何特定于空间的东西。
添加新对象¶
我们现在可以创建和插入新的 Lake
对象到数据库中,就像我们在PostGIS中使用GeoAlchemy 2一样。
>>> lake = Lake(name='Majeur', geom='POLYGON((0 0,1 0,1 1,0 1,0 0))')
>>> session.add(lake)
>>> session.commit()
我们现在可以查询数据库 Majeur
::
>>> our_lake = session.query(Lake).filter_by(name='Majeur').first()
>>> our_lake.name
u'Majeur'
>>> our_lake.geom
<WKBElement at 0x9af594c; '0103000000010000000500000000000000000000000000000000000000000000000000f03f0000000000000000000000000000f03f000000000000f03f0000000000000000000000000000f03f00000000000000000000000000000000'>
>>> our_lake.id
1
让我们添加更多的湖:
>>> session.add_all([
... Lake(name='Garde', geom='POLYGON((1 0,3 0,3 2,1 2,1 0))'),
... Lake(name='Orta', geom='POLYGON((3 0,6 0,6 3,3 3,3 0))')
... ])
>>> session.commit()
查询¶
让我们做一个简单的非空间查询:
>>> query = session.query(Lake).order_by(Lake.name)
>>> for lake in query:
... print(lake.name)
...
Garde
Majeur
Orta
现在是空间查询:
>>> from geolachemy2 import WKTElement
>>> query = session.query(Lake).filter(
... func.ST_Contains(Lake.geom, WKTElement('POINT(4 1)')))
...
>>> for lake in query:
... print(lake.name)
...
Orta
下面是另一个空间查询,使用 ST_Intersects
这次:
>>> query = session.query(Lake).filter(
... Lake.geom.ST_Intersects(WKTElement('LINESTRING(2 1,4 1)')))
...
>>> for lake in query:
... print(lake.name)
...
Garde
Orta
我们还可以将关系函数应用于 geoalchemy2.elements.WKBElement
. 例如::
>>> lake = session.query(Lake).filter_by(name='Garde').one()
>>> print(session.scalar(lake.geom.ST_Intersects(WKTElement('LINESTRING(2 1,4 1)'))))
1
session.scalar
允许执行子句并返回标量值(本例中为整数值)。
价值 1
表明“Garde”湖确实与 LINESTRING(2 1,4 1)
几何学。有关详细信息,请参见SpatiaLite SQL函数参考列表。