正确的SqlAlchemy查询使用contains\u

正确的SqlAlchemy查询使用contains\u,sqlalchemy,Sqlalchemy,我有一个问题,我已经找到了一个有效的解决方案。我不确定我是否正确执行了查询,我希望能找到答案。各表如下: 查询是: q = session.query(Person).outerjoin(PetOwner).join(Animal).options(contains_eager("petowner_set"), contains_eager("petowner_set.animal")) 人与宠物主人之间有关系 如果从person到petowner的连接和从petowner到animal的连

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

查询是:

q = session.query(Person).outerjoin(PetOwner).join(Animal).options(contains_eager("petowner_set"), contains_eager("petowner_set.animal"))
人与宠物主人之间有关系

如果从
person
petowner
的连接和从
petowner
animal
的连接都是内部连接或外部连接,这将很容易。但是,从
person
petowner
的连接是外部连接,从
petowner
animal
的连接是内部连接。为了实现这一点,我在选项中添加了两个
contains\u eager
调用


这是实现这一目标的正确方法吗?

简短回答:据我所知,你应该使用
外部连接
,除非你不想看到没有动物的

首先,让我们看一看
JOIN
s:

  • two-internal
    :在这种情况下,查询结果将只返回至少有一只动物的那些
    Person
    s(假设任何
    PetOwner.animal
    都不可为空)
  • 外部用于PetOwner,内部用于Animal
    :同上(再次假设任何
    PetOwner.Animal
    都不可为空)
  • 两个外部
    :查询结果将返回所有
    个人
    s,无论他们是否拥有动物
那么,
包含了什么呢?据报道,

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


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

我认为唯一的区别是您应该将调用链接到
contains\u eager
,如下所示:

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

请参阅:

我应该在问题中详细说明。我正在寻找执行数据加载的正确方法。我需要查询只调用一次,并且仍然能够访问petowner_集和每个petowner的宠物。在不加载数据的情况下执行此操作相当简单,但随后会变成一个n+1查询。我不确定我是否正确使用了contains\u eager。我最初尝试了outerjoin,但我需要一个outerjoin和一个innerjoin,正如我在问题中的查询一样。为什么需要
innerjoin
?嘘,我的意思是我最初尝试了joinedload\u all。我的问题是:joinedload_all(“petowner_set.animal”),它可以工作,但使它们都在外面。至于为什么我需要一个内部连接,fk pet on petowner是一个必填字段。没有宠物,宠物主人就无法生存。所以内部连接只是逻辑上的。我不是最擅长优化的,但我认为外层连接效率较低。是的,
innerjoin
是合乎逻辑的,但前提是你要孤立地查看
PetOwner->Pet
。但是,此
内部连接将过滤掉没有任何动物的
人。如果这是您想要的-很好,如果不是-您需要两个连接都是
外部的