使用 contains_eager 进行正确的 SqlAlchemy 查询

Div*_*yer 5 sqlalchemy

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

所有者

查询是:

q = session.query(Person).outerjoin(PetOwner).join(Animal).options(contains_eager("petowner_set"), contains_eager("petowner_set.animal"))
Run Code Online (Sandbox Code Playgroud)

将其与宠物主人连接起来的人之间存在关系。

如果连接 from persontopetowner和连接 from petownertoanimal都是内连接或都是外连接,那就很容易了。person但是,从到 的连接petowner是外连接,从petowner到 的连接animal是内连接。为了实现这一点,我添加了两个contains_eager对选项的调用。

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

van*_*van 5

简短回答: 据我所知,您应该同时使用outerjoin两者,除非您不想看到Persons谁没有动物

首先,让我们看一下JOINs:

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

那么,该怎么contains_eager办呢?根据文档

...将向查询指示应从查询中当前的列中立即加载给定的属性。

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