You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 18:43:16