为什么SQLAlchemy 1.4查询结果字典会忽略text()构造的列?
问题原因
你直接在sa.text()的SQL语句中写的as graphs别名仅在数据库执行层面生效,SQLAlchemy的结果解析逻辑不会自动从原生SQL片段中提取别名作为结果列的键,所以才会出现结果有值但keys()里没有对应列名的情况。
解决方法
有两种常用方案都可以满足你在PostgreSQL侧执行聚合的要求:
方案1(推荐):使用SQLAlchemy原生函数构造聚合逻辑
完全不用写原生SQL片段,通过sa.func调用PG的jsonb_agg函数,显式设置列标签:
stmt = sa.select( Quadrant.id, sa.func.jsonb_agg(Graph.data, order_by=Graph.id).label("graphs") ).outerjoin( Graph, Quadrant.id == Graph.quadrant_id ).group_by( Quadrant.id )
这种写法完全符合SQLAlchemy 1.4/2.0的语法规范,ORM可以自动识别列名,不需要硬编码SQL片段,后续维护更方便。
方案2:给原生SQL片段显式设置标签
如果你的聚合逻辑特别复杂,必须写原生SQL片段,可以用sa.literal_column()包裹SQL片段后调用label()方法设置列名:
stmt = sa.select( Quadrant.id, sa.literal_column("jsonb_agg(graph.data order by graph.id)").label("graphs") ).outerjoin( Graph, Quadrant.id == Graph.quadrant_id ).group_by( Quadrant.id )
可选优化
如果需要直接拿到字典格式的结果,可以在执行查询时调用mappings()方法,不需要自己再做转换:
with dbsession.begin(): res = dbsession.execute(stmt).mappings() for r in res: print(r.keys()) # 输出 ['id', 'graphs'] print(r['graphs']) # 直接按键取值
内容的提问来源于stack exchange,提问作者marcogh
相关产品推荐
相关产品推荐

