SQLAlchemy不支持直接設置返回函數,但其FunctionElement
s被認爲是FromClause
s,這意味着您已經可以將它們視爲表;我們只需要添加從函數中選擇特定列的功能。幸運的是,這是簡單的(雖然不是很明顯):從GenericFunction
from sqlalchemy.sql.base import ColumnCollection
from sqlalchemy.sql.expression import column
from sqlalchemy.sql.functions import FunctionElement
NormAddy = CompositeType(
"norm_addy",
[
Column("address", Integer),
Column("predirAbbrev", String),
Column("streetName", String),
Column("streetTypeAbbrev", String),
Column("postdirAbbrev", String),
Column("internal", String),
Column("location", String),
Column("stateAbbrev", String),
Column("zip", String),
Column("parsed", Boolean),
],
)
class geocode(GenericFunction):
columns = ColumnCollection(
Column("rating", Integer),
column("geomout"), # lowercase column because we don't have the `geometry` type
Column("addy", NormAddy),
)
子類在全球擁有註冊geocode
功能,以便爲預期func.geocode
將工作的額外好處。
g = func.geocode(func.pagc_normalize_address("1 Capitol Square Columbus OH 43215")).alias("g")
query = session.query(
g.c.rating,
func.ST_X(g.c.geomout).label("lon"),
func.ST_Y(g.c.geomout).label("lat"),
g.c.addy.address.label("stno"),
g.c.addy.streetName.label("street"),
g.c.addy.streetTypeAbbrev.label("styp"),
g.c.addy.location.label("city"),
g.c.addy.stateAbbrev.label("st"),
g.c.addy.zip,
).select_from(g)
不幸的是,這並不奏效。似乎有一個錯誤,使得g.c.addy.address
語法不適用於最新版本的SQLAlchemy。我們可以修復它真正的快速(雖然這應該真正固定在sqlalchemy_utils):
from sqlalchemy_utils.types.pg_composite import CompositeElement
import sqlalchemy_utils
class CompositeType(sqlalchemy_utils.CompositeType):
class comparator_factory(_CompositeType.comparator_factory):
def __getattr__(self, key):
try:
type_ = self.type.typemap[key]
except KeyError:
raise AttributeError(key)
return CompositeElement(self.expr, key, type_)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.typemap = {c.name: c.type for c in self.columns}
現在,它的工作原理:
print(query.statement.compile(engine))
# SELECT g.rating, ST_X(g.geomout) AS lon, ST_Y(g.geomout) AS lat, (g.addy).address AS stno, (g.addy).streetName AS street, (g.addy).streetTypeAbbrev AS styp, (g.addy).location AS city, (g.addy).stateAbbrev AS st, (g.addy).zip AS zip_1
# FROM geocode(pagc_normalize_address(%(pagc_normalize_address_1)s)) AS g
你有沒有看着['sqlalchemy_utils.types.pg_composite'(HTTP: //sqlalchemy-utils.readthedocs.io/en/latest/data_types.html#module-sqlalchemy_utils.types.pg_composite)? – univerio
我可以看到,如果我的複合類型是一個靜態表上的列的情況下,將如何工作,但在我的情況下,它是一個函數返回的複合類型。在我的設置中,我們沒有爲任何函數(僅限於表格)定義sqlalchemy類。對這部分問題有什麼想法? – BrianEdwardHoover