Python SQLAlchemy按需收集加载到包含多个项的结果集

Python SQLAlchemy按需收集加载到包含多个项的结果集,python,sqlalchemy,Python,Sqlalchemy,假设我有两个模型(A和B),它们之间有一对多的关系,那么在SQLAlchemy中有没有办法首先检索模型A的列表(可能以某种方式过滤掉): 。。。然后在结果查询集中加载与每个模型A相关的每个模型B(这一点非常重要!),这种方式不会触发n个SQL查询(其中n是结果A结果集中的模型数) 或(等效,但具有显式联接): 如果您不想在没有B对象的情况下加载A对象,请在第二个示例中使用join而不是outerjoin 如果您没有明确地将您的\u relation\u to \u B\u字段关系从B设置为A,那

假设我有两个模型(A和B),它们之间有一对多的关系,那么在SQLAlchemy中有没有办法首先检索模型A的列表(可能以某种方式过滤掉):

。。。然后在结果查询集中加载与每个模型A相关的每个模型B(这一点非常重要!),这种方式不会触发n个SQL查询(其中n是结果A结果集中的模型数)

或(等效,但具有显式联接):

如果您不想在没有B对象的情况下加载A对象,请在第二个示例中使用
join
而不是
outerjoin


如果您没有明确地将
您的\u relation\u to \u B\u字段
关系从B设置为A,那么这将是名称,在B到A的关系中的backref(或back\u populates)选项中指定。

我建议
子查询加载。如果您总是以这种方式使用模型,请继续在关系
关系(“modelb”,lazy=“subquery”)

如果您并不总是希望它以这种方式运行(例如,您以各种方式使用模型A),那么您可以在查询时设置该选项

定义了
ModelA
ModelB
类,ModelA与ModelB之间存在称为“ModelB_项”的关系

这里需要了解的重要一点是,只有2条SQL SELECT语句执行过


如果将items循环包装在从不执行的If语句中,则只执行第一个sqlselect。无论有多少个模型对象,第二个选择(即使在循环中)只执行一次。正如另一个答案所指出的,您可以执行joinedload,但这还存在其他问题(例如添加额外的outerjoin)。您可以根据您的需要使用任何一个。

获取B型实例的所有ID,然后执行
SELECT*FROM。。。其中id位于…
query中。显然,这不会在结果集中的每个模型上填充relationship属性,这正是我想要的。
resultsA = session.query(A).filter(company_id=3).all()
from sqlalchemy.orm import joinedload

results_A = (session.query(A)
        .filter(A.company_id==3)
        .options(joinedload(A.your_relation_to_B_field))
        .all()) # will load all related B objects in one query
results_B_0 = results_A[0].your_relation_to_B_field #won't trigger sql
from sqlalchemy.orm import contains_eager

results_A = (session.query(A)
        .outerjoin(A.your_relation_to_B_field)
        .filter(A.company_id==3)
        .options(contains_eager(A.your_relation_to_B_field))
        .all()) # will load all related B objects in one query
results_B_0 = results_A[0].your_relation_to_B_field #won't trigger sql
query = session.query(ModelA).filter(ModelA.stuff == 'GoodStuff').options(subqueryload(ModelA.modelb_items))
for a in query: # fires single sql SELECT to get ModelA items
    print a.name

    # fires single sql SELECT to get ALL related ModelB items.
    for item in a.modelb_items: 
        print item.modelb_property