Bor*_*jaX 6 python sqlalchemy relationship
假设我有这样一个类:
class Foo(declarativeBase):
bars1 = relationship(Bar.Bar, secondary=foos_to_bars1, collection_class=set())
bars2 = relationship(Bar.Bar, secondary=foos_to_bars2, collection_class=list())
Run Code Online (Sandbox Code Playgroud)
(每个关系都给了我"Bar"一定的条件).在某一点上,我想在任何关系中获得具有"bar"(Bar.Bar实例)的"Foo"实例.
如果我尝试做:
def inAnyBar(bar)
query(Foo).filter(or_(Foo.bars1.contains(bar), Foo.bars2.contains(bar)).all()
Run Code Online (Sandbox Code Playgroud)
我得到一个空洞的结果.
看起来(对我来说)就像我做的那样:
query(Foo).join(Foo.bars1).filter(Foo.bars1.contains(bar)).\
join(Foo.bars2).filter(Foo.bars1.contains(bar))
Run Code Online (Sandbox Code Playgroud)
由于Foo.bars1不包含bar,因此第二个过滤器会显示空结果.
我已经能够找到一个子查询的解决方法(子查询中的每个连接+过滤器,然后或所有子查询),但我想知道是否有更好的方法来做...
我发现了这个:http: //techspot.zzzeek.org/2008/09/09/selecting-booleans/
这就是我想做的事情,但它适用于SqlAlchemy 0.5而且我(几乎)确定使用SqlAlchemy 0.6.6有一种"更清洁"的方法
谢谢!
你是对的,session.query(Foo).filter(Foo.bars1.contains(bar)|Foo.bars2.contains(bar))产生以下 SQL:
SELECT "Foo".id AS "Foo_id"
FROM "Foo", foos_to_bars1 AS foos_to_bars1_1, foos_to_bars2 AS foos_to_bars2_1
WHERE "Foo".id = foos_to_bars1_1.foo AND ? = foos_to_bars1_1.bar OR
"Foo".id = foos_to_bars2_1.foo AND ? = foos_to_bars2_1.bar
Run Code Online (Sandbox Code Playgroud)
当其中一个secondary表为空时,它会返回错误的结果。看起来像是 SQLAlchemy 中的一个错误。但是替换contains()为any()修复了问题(它使用 EXISTS 子查询):
session.query(Foo).filter(Foo.bars1.any(id=bar.id)|Foo.bars2.any(id=bar.id))
Run Code Online (Sandbox Code Playgroud)
您还可以显式指定 OUTER JOIN:
Bar1 = aliased(Bar)
Bar2 = aliased(Bar)
session.query(Foo).outerjoin((Bar1, Foo.bars1)).outerjoin((Bar2, Foo.bars2))\
.filter((Bar1.id==bar.id)|(Bar2.id==bar.id))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5213 次 |
| 最近记录: |