SqlAlchemy:检查一个对象是否处于任何关系中(or_(object.relationship1.contains(otherObject),object.relationship2.contains(otherObject))

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有一种"更清洁"的方法

谢谢!

Den*_*ach 4

你是对的,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)