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 или дополнительного оператора соединения), мне нужен фильтр такого типа более одного раза.
Даже если нет простого решения, я с удовольствием получу все ответы.
Ответы
Ответ 1
Использовать метод has()
отношений (более читаемый):
patients = Patient.query.filter(Patient.mother.has(phenoscore=10))
или присоединиться (обычно быстрее):
patients = Patient.query.join(Patient.mother, aliased=True)\
.filter_by(phenoscore=10)
Ответ 2
Вы должны запросить отношения с помощью соединения
Вы получите пример из этой стратегии само-ссылочного запроса
Ответ 3
Хорошие новости для вас: Недавно я сделал пакет, который дает вам фильтрацию/сортировку со "магическими" строками как в 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
Ответ 4
Я использовал его с сеансами, но альтернативный способ прямого доступа к полю отношений -
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)