SQLAlchemy 2.0+多对多关联查询:仅获取指定列数据
解决SQLAlchemy多对多关联仅查询指定列的问题
针对你的需求(获取包含书籍标题列表的Shop对象/结构),以下是两种可行的解决方案,适配Python 3.9+和SQLAlchemy 2.0+版本:
方案一:基于ORM对象加载指定列并转换结果
这种方式会返回Shop ORM对象,同时仅加载关联Book的title列,避免加载多余的pages关联数据:
from sqlalchemy.orm import selectinload, load_only, raiseload # 查询Shop并加载指定列的关联Book shops = session.execute( select(Shop) .options( # 加载Shop的books关联,仅加载Book的title字段 selectinload(Shop.books).load_only(Book.title), # 阻止加载Book的pages关联,避免懒加载触发多余查询 raiseload(Book.pages) ) ).scalars().all() # 将每个Shop的books属性转换为标题列表 for shop in shops: shop.books = [book.title for book in shop.books] print(shop) # 输出格式:Shop(id=1, books=["book1", "book2", ...])
你之前尝试的问题点:
- 第二个方案中
selectinload(Book)路径错误,应该指定Shop.books(Shop模型的关联属性); - 未添加
raiseload(Book.pages)导致Book的pages关联可能被懒加载,返回多余的Page对象。
方案二:直接聚合查询获取结构化数据
如果不需要ORM对象,仅需要目标格式的数据,可使用SQL聚合函数直接分组查询,性能更优:
from sqlalchemy import func # 聚合查询店铺及其关联书籍的标题列表 result = session.execute( select( Shop.id, Shop.name, func.array_agg(Book.title).label("books") ) .join(Shop.books) # 关联Shop和Book的多对多关系 .group_by(Shop.id) # 按店铺分组 ).all() # 输出目标格式 for shop_id, _, books in result: print(f"Shop(id={shop_id}, books={books})")
你之前尝试的问题点:
- 第一个查询未关联Shop和Book,也未分组,会得到笛卡尔积的零散结果,无法按店铺聚合书籍列表;
- 误用了
Book.name,你的Book模型中对应的字段是title。
内容的提问来源于stack exchange,提问作者Farfax
相关产品推荐
相关产品推荐

