编辑:以下片段似乎是正确的方法:
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:与 UserGadget.gadget 关联的“InstrumentedAttribute”对象和“Comparator”对象都没有属性“gadgetComponents”
关于我做错了什么的任何想法,或者是否有更好的方法在 SQLAlchemy 中执行此类查询?
最佳答案
join() 是更好的方法,因为 any() 会产生大量昂贵的嵌套子查询。但是您在使用“any”时犯的错误是使用了如下语法:UserGadget.gadget.components
。 SQLAlchemy 不会像这样在系列中继续属性的命名空间,例如没有 UserGadget.gadget.components
;分别只有 UserGadget.gadget
和 Gadget.components
。就像 SQL 不会让你说“SELECT * from user_gadget.gadget_id.gadget.component_id”之类的东西一样,SQLAlchemy 需要你告诉它你想如何将你正在查询的多个表连接在一起。使用 any()
时,它类似于 any(and_(UserGadget.gadget_id == GadgetComponent.gadget_id))
,但在任何情况下使用 JOIN 都更好。
关于python - 链中存在多个一对多映射的长链存在查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21230065/