SqlAlchemy - Memfilter berdasarkan Atribut Relasi


94

Saya tidak punya banyak pengalaman dengan SQLAlchemy dan saya punya masalah, yang tidak bisa saya pecahkan. Saya mencoba mencari dan saya mencoba banyak kode. Ini adalah Kelas saya (dikurangi menjadi kode yang paling signifikan):

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)

dan saya ingin menanyakan semua pasien, yang fenoscore ibunya (misalnya) == 10

Seperti yang diceritakan, saya mencoba banyak kode, tetapi saya tidak mengerti. Solusi logisnya, di mata saya, adalah

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

karena, Anda dapat mengakses .mother.phenoscoresetiap elemen saat mengeluarkan tetapi, kode ini tidak melakukannya.

Apakah ada kemungkinan (langsung) untuk memfilter berdasarkan atribut hubungan (tanpa menulis Pernyataan SQL, atau pernyataan gabungan tambahan), saya memerlukan filter semacam ini lebih dari satu kali.

Meskipun tidak ada solusi yang mudah, saya senang mendapatkan semua jawaban.

Jawaban:


169

Gunakan metode has()hubungan (lebih mudah dibaca):

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

atau bergabung (biasanya lebih cepat):

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

9
pasien = Patient.query.filter (Patient.mother.has (Patient.phenoscore == 10))
pengguna1105851

@ user1105851 has()mendukung kedua ekspresi kondisi sebagai argumen tanpa nama dan filter_byargumen kata kunci -gaya. Nanti tampaknya lebih mudah dibaca oleh saya.
Denis Otkidach

@DenisOtkidach benar, tapi itu akan terjadi phenoscore = 10. filter_byhanya mengambil kata kunci kesetaraan (karena itu hanya melakukan ** kwargs pada mereka)
aruisdante

@aruisdante Anda benar, itu keliru edit jawabannya.
Denis Otkidach

4
gunakan salah satu sebagai gantinya: patient = Patient.query.filter (Patient.mother.any (phenoscore = 10))
Boston Kenne


7

Saya menggunakannya dengan sesi, tetapi cara alternatif di mana Anda dapat mengakses bidang hubungan secara langsung adalah

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

Saya belum mengujinya, tapi saya rasa ini juga akan berhasil

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


0

Ini adalah jawaban yang lebih umum tentang cara menanyakan hubungan.

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

Ini memungkinkan Anda untuk:

parent_obj.some_relationship.filter(ParentClass.some_attr==True).all()
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.