SQLAlchemy JOIN查询双模型结果的属性高效合并方法咨询
场景说明
当执行如下SQLAlchemy查询语句时:
session.query(BaseModel, JoinModel).join(JoinModel, BaseModel.id == JoinModel.id, isouter=True)
得到的查询结果为如下格式的元组序列:
(<__main__.BaseModel object at 0x000001E32BC81220>, <__main__.JoinModel object at 0x000001E32A15BE50>) (<__main__.BaseModel object at 0x000001E32BC81220>, <__main__.JoinModel object at 0x000001E32A15BC70>) (<__main__.BaseModel object at 0x000001E32BC81220>, <__main__.JoinModel object at 0x000001E32A317670>)
可对其中的BaseModel或JoinModel对象调用.__dict__方法获取其属性值,以下是将同一条结果中两个对象的属性合并为单一属性集合的高效方法:
可用高效方案
方案1:遍历实时合并(适合小数据集,代码极简)
时间复杂度为O(n),无额外IO开销,属于轻量实现:
merged_result = [] query_res = session.query(BaseModel, JoinModel).join(JoinModel, BaseModel.id == JoinModel.id, isouter=True) for base_obj, join_obj in query_res: # 后解包的字段会覆盖前者的同名字段,可按需调整顺序 merged_dict = {**base_obj.__dict__, **join_obj.__dict__} # 剔除SQLAlchemy内置的实例状态字段 merged_dict.pop("_sa_instance_state", None) merged_result.append(merged_dict)
如果两个模型存在同名字段,可调整解包顺序,或单独给重名字段赋值自定义key。
方案2:查询时直接返回扁平化结果(适合大数据集,性能最优)
查询阶段就指定返回所有需要的字段,避免返回ORM对象的额外开销:
# 收集两个模型的所有字段,重名字段可通过.label()设置别名避免冲突 base_columns = [getattr(BaseModel, col.name) for col in BaseModel.__table__.columns] join_columns = [getattr(JoinModel, col.name).label(f"join_{col.name}") for col in JoinModel.__table__.columns] all_columns = base_columns + join_columns # 查询后直接转字典,无需额外处理对象属性 query_res = session.query(*all_columns).join(JoinModel, BaseModel.id == JoinModel.id, isouter=True) merged_result = [row._asdict() for row in query_res]
方案3:惰性取值包装类(适合需要保留ORM对象方法的场景)
无需提前遍历所有属性,使用时才动态取值,性能损耗极低:
class MergedORMObj: def __init__(self, base_obj, join_obj): self.base = base_obj self.join = join_obj def __getattr__(self, item): # 优先从base对象取值,取不到再取join对象的属性 if hasattr(self.base, item): return getattr(self.base, item) return getattr(self.join, item) # 使用时直接实例化即可 query_res = session.query(BaseModel, JoinModel).join(JoinModel, BaseModel.id == JoinModel.id, isouter=True) merged_objs = [MergedORMObj(base, join) for base, join in query_res]
内容的提问来源于stack exchange,提问作者Minura Punchihewa
相关产品推荐
相关产品推荐

