繁体   English   中英

在SQLAlchemy中按链接对象键过滤查询

[英]Filter query by linked object key in SQLAlchemy

从标题来看, 将是完全相同的问题,但是我看不到任何答案如何适用于我的用例:

我有两个班级,并且他们之间有关系:

treatment_association = Table('tr_association', Base.metadata,
    Column('chronic_treatments_id', Integer, ForeignKey('chronic_treatments.code')),
    Column('animals_id', Integer, ForeignKey('animals.id'))
)

class ChronicTreatment(Base):
    __tablename__ = "chronic_treatments"
    code = Column(String, primary_key=True)

class Animal(Base):
    __tablename__ = "animals"
    treatment = relationship("ChronicTreatment", secondary=treatment_association, backref="animals")

我希望只能选择经过代码“ X”处理的动物。 我尝试了很多方法。

这个失败,并带有AttributeError

sql_query = session.query(Animal.treatment).filter(Animal.treatment.code == "chrFlu")
for item in sql_query:
    pass

mystring = str(session.query(Animal))

这很高兴地返回了未过滤动物的列表:

sql_query = session.query(Animal.treatment).filter(ChronicTreatment.code == "chrFlu")
for item in sql_query:
    pass

mystring = str(session.query(Animal))

我可以将上述线程中与示例最接近的东西放在一起:

subq = session.query(Animal.id).subquery()
sql_query = session.query(ChronicTreatment).join((subq, subq.c.treatment_id=="chrFlu"))
for item in sql_query:
    pass

mystring = str(session.query(Animal))
mydf = pd.read_sql_query(mystring,engine)

也失败,并出现AttributeError

您能帮我对这个列表进行排序吗?

首先,表定义存在两个问题:

1)在treatment_association你有Integer列指向chronic_treatments.codecodeString列。

我认为最好在chronic_treatments使用一个整数id ,这样您就不必在另一个表中重复该字符串代码,并且以后也有机会将更多字段添加到chronic_treatments中。 更新:并不完全正确,您仍然可以添加更多字段,但是如果您决定重命名,则更改“代码”会更加复杂。

2)在Animal模型中,您有一个名为treatment的关系。 这是令人困惑,因为你有很多一对多的关系,应该是复数- treatments

修复以上两个问题之后,应该更清楚为什么您的查询不起作用。 这个(我用treatment代替treatments

sql_query = session.query(Animal.treatments).filter(
    Animal.treatments.code == "chrFlu")

Animal.treatments表示多对多关系,它不是SQL Alchemy模式,因此您不能将其传递给query也不能在filter使用。

下一个由于相同的原因而无法工作(您将Animal.treatments传递到query

最后一个更接近,您实际上需要join才能获得结果。

我认为将查询理解为SQL更容易了(无论如何,您都需要了解SQL才能使用sqlalchemy):

animals = session.query(Animal).from_statement(text(
    """
       select distinct animals.* from animals
       left join tr_association assoc on assoc.animals_id = animals.id
       left join chronic_treatments on chronic_treatments.id = assoc.chronic_treatments_id
       where chronic_treatments.code = :code
 """)
).params(code='chrFlu')

它将选择animals并通过tr_association加入chronic_treatments tr_association并通过代码过滤结果。

有了这个,很容易使用无SQL语法重写它:

sql_query = session.query(Animal).join(Animal.treatments).filter(
    ChronicTreatment.code == "chrFlu")

这将返回您想要的-用给定代码进行了相关慢性治疗的动物列表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM