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

异步SQLAlchemy+FastAPI一对多关联查询报错求助

解决SQLAlchemy异步查询中关联集合预加载的InvalidRequestError错误

直接修改异步接口的结果处理逻辑,添加unique()方法即可解决问题,完整代码如下:

@router.get("/testing", response_model=List[WebsiteOut], response_model_exclude_none=True)
async def all_websites(
        user_filter: WebsiteFilter = FilterDepends(WebsiteFilter),
        session: AsyncSession = Depends(get_session)
):
    query = select(Websites)
    query = query.distinct()
    query = query.join(Websites.website_services)
    query = query.options(contains_eager(Websites.website_services))
    query = query.filter(WebsiteServices.disabled == False)

    query = user_filter.filter(query)
    query = user_filter.sort(query)

    result = await session.execute(query)

    return result.scalars().unique().all()

原因解析

当通过contains_eager预加载一对多关联集合(如Websites.website_services)并执行JOIN查询时,SQL会返回多条包含重复父对象的结果行(每个子对象对应一行)。虽然你在SQL层面添加了distinct()去重,但ORM层面需要进一步处理对象实例的去重与聚合,确保每个Websites对象仅返回一次,同时正确组装其关联的服务集合。

同步模式下的db.query(Websites).all()会自动处理这个对象去重逻辑,而异步模式使用Core风格的select查询时,必须显式调用unique()方法触发ORM层面的去重,否则就会抛出InvalidRequestError。

效果验证

修改后,异步接口将返回与同步版本完全一致的结果:

[
    {
        "url": "https://www.******.com",
        "tat": 10,
        "website_services": [
            {
                "service_name": "cbd",
                "service_cost": 250,
                "website_id": 26
            },
            {
                "service_name": "guest_post",
                "service_cost": 100,
                "website_id": 26
            }
        ]
    },
    {
        "url": "https://www.*************.com",
        "tat": 10,
        "website_services": [
            {
                "service_name": "guest_post",
                "service_cost": 150,
                "website_id": 13
            }
        ]
    }
]

内容的提问来源于stack exchange,提问作者Erez Bentovim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:20:39