使用contains_eager进行正确的SqlAlchemy查询

时间:2012-07-19 18:41:05

标签: sqlalchemy

我有一个查询,我找到了一个有效的解决方案。我不确定我是否正确执行查询,我希望能找到答案。表格如下:

owner

查询是:

q = session.query(Person).outerjoin(PetOwner).join(Animal).options(contains_eager("petowner_set"), contains_eager("petowner_set.animal"))

将人们与宠物主人联系起来是有关系的。

如果从personpetowner的加入以及从petowneranimal的加入都是内部联接或两个外部联接,那将很容易。但是,从personpetowner的联接是外联接,从petowneranimal的联接是内联接。为此,我在选项中添加了两个contains_eager次调用。

这是完成此任务的正确方法吗?

2 个答案:

答案 0 :(得分:4)

简答: 从我所看到的情况来看,您应该使用outerjoin两者,除非您不希望看到Persons没有动物

首先,让我们看看JOIN s:

  • both INNER:在这种情况下,您的查询结果将返回那些至少有一只动物的Person(假设任何PetOwner.animal是不可空的)
  • OUTER for PetOwner, INNER for Animal:与上述相同(同样,假设任何PetOwner.animal不可为空)
  • both OUTER:您的查询结果将返回所有 Person s,无论他们是否拥有Animal

那么contains_eager做了什么?根据{{​​3}},

  

...将向查询指出应该从当前查询中的列急切加载给定属性。

这意味着当您访问Person.petowner_set时,不需要额外的数据库查询,因为SA将从原始查询加载关系。这绝对不会影响JOINs的工作方式,只会影响关系的加载。这只是一个数据加载优化。

答案 1 :(得分:1)

我认为唯一的区别是您应该将呼叫链接到contains_eager,如下所示:

q = (session.query(Person)
    .outerjoin(PetOwner)
    .join(Animal)
    .options(
      contains_eager("petowner_set").contains_eager("petowner_set.animal")
    )
)

请参阅:https://docs.sqlalchemy.org/en/latest/orm/loading_relationships.html#controlling-loading-via-options