Je n'ai pas beaucoup d'expérience avec SQLAlchemy et j'ai un problème que je ne peux pas résoudre. J'ai essayé de chercher et j'ai essayé beaucoup de code. Voici ma classe (réduite au code le plus significatif):
class Patient(Base):
__table= '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)
et je voudrais interroger tous les patients, dont le phénoscore de la mère est (par exemple) == 10
Comme dit, j'ai essayé beaucoup de code, mais je ne comprends pas. La solution logique, à mes yeux, serait
patients = Patient.query.filter(Patient.mother.phenoscore == 10)
car, vous pouvez accéder à .mother.phenoscore
pour chaque élément lors de la sortie mais, ce code ne le fait pas.
Y a-t-il une possibilité (directe) de filtrer par un attribut d'une relation (sans écrire l'instruction SQL, ou une instruction join supplémentaire), j'ai besoin de ce type de filtre plus d'une fois.
Même s'il n'y a pas de solution facile, je suis heureux d'obtenir toutes les réponses.
Utilisez la méthode has()
de la relation (plus lisible):
patients = Patient.query.filter(Patient.mother.has(phenoscore=10))
ou rejoindre (généralement plus rapide):
patients = Patient.query.join(Patient.mother, aliased=True)\
.filter_by(phenoscore=10)
Vous devez interroger la relation avec join
Vous obtiendrez l'exemple de ceci Stratégies de requête auto-référentielle
Bonne nouvelle pour vous: j'ai récemment créé un package qui vous permet de filtrer/trier avec des chaînes "magiques" comme dans Django , vous pouvez donc maintenant écrire quelque chose comme
Patient.where(mother___phenoscore=10)
C'est beaucoup plus court, en particulier pour les filtres complexes, disons,
Comment.where(post___public=True, post___user___name__like='Bi%')
J'espère que vous apprécierez ce forfait
https://github.com/absent1706/sqlalchemy-mixins#Django-like-queries
Je l'ai utilisé avec des sessions, mais une autre façon d'accéder directement au champ de la relation est
db_session.query(Patient).join(Patient.mother) \
.filter(Patient.mother.property.mapper.class_.phenoscore==10)
Je ne l'ai pas testé, mais je suppose que cela fonctionnerait aussi
Patient.query.join(Patient.mother) \
.filter(Patient.mother.property.mapper.class_.phenoscore==10)