编辑:下面这篇文章似乎是对的:session.query(User).join("userGadgets", "gadget", "components","gadgetComponentMetals")
原件:
我配置了以下表格:
class User(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True)
name = Column(String)
class Gadget(Base):
__tablename__ = "gadget"
id = Column(Integer, primary_key=True)
brand = Column(String)
class UserGadget(Base):
__tablename__ = "user_gadget"
user_id = Column(Integer, ForeignKey('user.id'), primary_key=True)
gadget_id = Column(Integer, ForeignKey('gadget.id'), primary_key=True)
user = relationship("User", backref=backref('userGadgets', order_by=user_id))
gadget = relationship("Gadget", backref=backref('userGadgets', order_by=gadget_id))
class GadgetComponent(Base):
__tablename__ = "gadget_component"
id = Column(String, primary_key=True)
gadget_id = Column(Integer,ForeignKey('gadget.id'))
component_maker = Column(String)
host = relationship("Gadget", backref=backref('components', order_by=id))
class ComponentUsingMetal(Base):
__tablename__ = "component_metal"
id = Column(Integer, primary_key=True)
component_id = Column(Integer, ForeignKey('GadgetComponent.id'))
metal = Column(String)
component = relationship("GadgetComponent", backref=backref('gadgetComponentMetals', order_by=id))
我想为拥有至少一个包含某种金属的组件的小工具的用户查找所有用户名。对此的SQL查询大致如下:
SELECT distinct u.name FROM user u join user_gadget ug on (u.id = ug.user_id) join gadget_component gc on (ug.gadget_id = gc.id) join component_metal cm on (gc.id = cm.component_id) order by u.name
我试过不同的版本:
session.query(User).filter(User.userGadgets.any(UserGadget.gadget.components.any(GadgetComponent.gadgetComponentMetals.exists())))
我得到以下错误:
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with UserGadget.gadget has an attribute 'gadgetComponents'
关于我做错了什么,有什么想法吗?或者有更好的方法在SQLAlchemy中进行这种查询吗?
最佳答案
join()是更好的方法,因为any()将生成许多昂贵的嵌套子查询。但是,您在“any”中犯的错误是使用了如下语法:UserGadget.gadget.components
。SQLAlchemy不会在这样的序列中继续属性的名称空间,例如,没有UserGadget.gadget.components
;只有UserGadget.gadget
和Gadget.components
,分别存在。就像SQL不会让你说“从用户gadget.gadget\u id.gadget.component\u id中选择*”之类的话,SQLAlchemy需要你告诉它你想如何将多个查询表连接在一起。在这里使用any()
会有点像any(and_(UserGadget.gadget_id == GadgetComponent.gadget_id))
,但是在任何情况下使用JOIN都更好。
关于python - 长链存在查询,在链中具有多个一对多映射,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21230065/