SqlAlchemy-фильтрация по атрибуту отношения


у меня нет большого опыта работы с 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)

и я хотел бы запросить всех пациентов, чей феноскор матери (например)== 10

как уже было сказано, я пробовал много кода, но я не понимаю. Логически решение, на мой взгляд, было бы

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

потому что вы можете получить доступ к .mother.phenoscore для каждый элемент при выводе, но этот код не делает этого.

есть ли (прямая) возможность фильтровать по атрибуту отношения (без написания оператора SQL или дополнительного оператора join), мне нужен этот вид фильтра более одного раза.

даже если нет простого решения, я рад получить все ответы.

4 58

4 ответа:

способ применения has() отношения (более читабельно):

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

или присоединиться (обычно быстрее):

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

вы должны запросить relationsip с join

вы получите пример из этой Стратегии Самореферентных Запросов

хорошая новость для вас: я недавно сделал пакет, который дает вам фильтрацию / сортировку с" волшебными " строками как в 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

я использовал его с сеансами, но альтернативным способом, где вы можете получить доступ к полю отношений напрямую, является

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)