web-dev-qa-db-de.com

SqlAlchemy - Filtern nach Beziehungsattributen

Ich habe nicht viel Erfahrung mit SQLAlchemy und ich habe ein Problem, das ich nicht lösen kann. Ich habe versucht zu suchen und ich habe viel Code ausprobiert. Dies ist meine Klasse (auf den wichtigsten Code reduziert):

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)

und ich möchte alle Patienten befragen, deren Mutters Phenoscore ist (zum Beispiel) == 10

Wie gesagt, ich habe viel Code ausprobiert, aber ich verstehe ihn nicht. Die logische Lösung wäre in meinen Augen

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

sie können bei der Ausgabe für jedes Element auf .mother.phenoscore zugreifen, dieser Code tut dies jedoch nicht.

Gibt es eine (direkte) Möglichkeit, nach einem Attribut einer Beziehung zu filtern (ohne die SQL-Anweisung oder eine zusätzliche Join-Anweisung zu schreiben), benötige ich diese Art von Filter mehr als einmal.

Auch wenn es keine einfache Lösung gibt, freue ich mich über alle Antworten.

79
user1105851

Verwenden Sie die Methode has() der Beziehung (besser lesbar):

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

oder beitreten (normalerweise schneller):

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

Sie müssen die Beziehung zu join abfragen

Sie erhalten daraus das Beispiel Self-Referential Query Strategies

11
Nilesh

Gute Nachrichten für Sie: Ich habe kürzlich ein Paket erstellt, mit dem Sie mit "magischen" Zeichenfolgen filtern/sortieren können wie in Django , sodass Sie jetzt so etwas wie schreiben können

Patient.where(mother___phenoscore=10)

Es ist viel kürzer, vor allem für komplexe Filter, sagen wir,

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

Ich hoffe, Sie werden dieses Paket genießen

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

Ich habe es bei Sitzungen verwendet, aber eine andere Möglichkeit, direkt auf das Beziehungsfeld zuzugreifen, ist

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

Ich habe es nicht getestet, aber ich denke, das würde auch funktionieren

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