SqlAlchemy-按关系属性过滤


93

我在SQLAlchemy上没有太多经验,并且有一个我无法解决的问题。我尝试搜索,并且尝试了很多代码。这是我的课程(简化为最重要的代码):

class Patient(Base):
    __tablename__ = 'patients'
    id = Column(Integer, primary_key=True, nullable=False)
    mother_id = Column(Integer, ForeignKey('patients.id'), index=True)
    mother = relationship('Patient', primaryjoin='Patient.id==Patient.mother_id', remote_side='Patient.id', uselist=False)
    phenoscore = Column(Float)

我想查询所有母亲的phenoscore为(例如)的患者 == 10

如前所述,我尝试了很多代码,但我不明白。在我看来,合乎逻辑的解决方案是

patients = Patient.query.filter(Patient.mother.phenoscore == 10)

因为,您可以.mother.phenoscore在输出时访问每个元素,但是此代码不执行此操作。

是否有(直接)可能性通过关系的属性进行过滤(而无需编写SQL语句或额外的连接语句),所以我需要多次进行这种过滤。

即使没有简单的解决方案,我也很高兴获得所有答案。

Answers:


167

has()关系的使用方法(更具可读性):

patients = Patient.query.filter(Patient.mother.has(phenoscore=10))

或加入(通常更快):

patients = Patient.query.join(Patient.mother, aliased=True)\
                    .filter_by(phenoscore=10)

9
病人= Patient.query.filter(Patient.mother.has(Patient.phenoscore == 10))
user1105851 2011年

@ user1105851 has()支持条件表达式作为未命名参数和filter_by-style关键字参数。后者对我来说似乎更具可读性。
Denis Otkidach 2011年

@DenisOtkidach是正确的,但随后会是phenoscore = 10filter_by只接受相等关键字(因为它只是对它们执行**操作)
aruisdante 2014年

@aruisdante你是对的,这是对答案的错误编辑。
Denis Otkidach 2014年

4
请改用any:患者= Patient.query.filter(Patient.mother.any(phenoscore = 10))
波士顿肯尼


7

我在会话中使用了它,但是可以直接访问关系字段的另一种方法是

db_session.query(Patient).join(Patient.mother) \
    .filter(Patient.mother.property.mapper.class_.phenoscore==10)

我没有测试过,但是我想这也可以

Patient.query.join(Patient.mother) \
    .filter(Patient.mother.property.mapper.class_.phenoscore==10)

5

对您来说是个好消息:我最近制作了一个软件包,可以像Django一样使用“神奇”字符串进行过滤/排序,因此您现在可以编写类似

Patient.where(mother___phenoscore=10)

它要短很多,尤其是对于复杂的过滤器而言,

Comment.where(post___public=True, post___user___name__like='Bi%')

希望你会喜欢这个套餐

https://github.com/absent1706/sqlalchemy-mixins#django-like-queries


0

这是有关如何查询关系的更一般的答案。

relationship(..., lazy='dynamic', ...)

这使您可以:

parent_obj.some_relationship.filter(ParentClass.some_attr==True).all()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.