【问题标题】:How to bulk load relations in sqlalchemy for a subset of parents?如何在 sqlalchemy 中为父子集批量加载关系?
【发布时间】:2021-01-08 13:04:06
【问题描述】:

假设我有两个具有一对多关系的模型 Blog 和 Comment。

class Blog(Base):
    id = Column(Integer, primary_key=True)
    comments = relationship("Comment")

class Comment(Base):
    id = Column(Integer, primary_key=True)
    blog = relationship("Blog")

我可以使用这样的子查询有效地查询博客及其 cmets

session.query(Blog).filter(...filter_criteria...).options(subqueryload(Blog.comments)).all()

这会发出两个单独的查询 - 一个用于加载博客,另一个用于加载 cmets。

如果我已经查询了一堆博客对象,我该如何加载 cmets?我在获取博客时不能使用 subqueryload 的原因是应用程序逻辑使用了需要 cmets 的子集博客。

换句话说,如果我在一个列表中有 5 个博客对象,有没有办法有效地加载 cmets,以便我可以通过这种方式访问​​它们:

blogs = [b1, b2, b3, b4, b5]
# Do something here to efficiently load comments
for blog in blogs:
    blog.comments

【问题讨论】:

    标签: sqlalchemy


    【解决方案1】:

    鉴于您已经加载了博客对象,那么为了“高效”,您应该最多发出 1 个查询来加载这些博客对象的 cmets。

    blogs = [b1, b2, b3, b4, b5]
    blog_ids = [blog.id for blog in blogs]    
    comments = session.query(Comment).filter(Comment.blog_id.in_(blog_ids)).all()
    

    这假定blog_idComment 上的fk 列。

    SQLAlchemy 会跟踪您在给定事务期间加载的所有对象,并且不会发出查询来加载已加载的对象。这是使用Identity Map Pattern

    查看此other SO question 及其答案。

    请注意,使用此“in_”子句可能是最有效的查询,也可能不是最有效的查询,具体取决于您的架构和传递的 blog_id 数量,但它可能与您需要的一样高效。

    【讨论】:

      猜你喜欢
      • 2019-10-02
      • 1970-01-01
      • 2023-03-29
      • 2014-03-27
      • 2017-06-29
      • 2019-01-18
      • 2012-10-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多