it-swarm-pt.tech

SqlAlchemy - Filtrando por Atributo de Relacionamento

Não tenho muita experiência com SQLAlchemy e tenho um problema que não consigo resolver. Eu tentei pesquisar e tentei muito código. Esta é minha classe (reduzida ao código mais significativo):

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)

e gostaria de consultar todos os pacientes, cujo fenomenore da mãe é (por exemplo) == 10

Como já foi dito, tentei muito código, mas não o entendi. A solução lógica, aos meus olhos, seria

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

porque, você pode acessar .mother.phenoscore para cada elemento ao emitir, mas esse código não faz isso.

Existe uma possibilidade (direta) de filtrar por um atributo de um relacionamento (sem escrever a instrução SQL ou uma instrução de junção extra), eu preciso desse tipo de filtro mais de uma vez.

Mesmo que não haja uma solução fácil, fico feliz em obter todas as respostas.

79
user1105851

Use o método has() do relacionamento (mais legível):

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

ou participar (geralmente mais rápido):

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

Você precisa consultar o relacionamento com join

Você obterá o exemplo disso Estratégias de consulta autorreferencial

11
Nilesh

Boas notícias para você: criei recentemente um pacote que permite filtrar/classificar com strings "mágicos" como no Django , então agora você pode escrever algo como

Patient.where(mother___phenoscore=10)

É muito mais curto, especialmente para filtros complexos, por exemplo,

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

Espero que você goste deste pacote

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

3
Alexander Litvinenko

Usei-o com sessões, mas uma maneira alternativa de acessar diretamente o campo de relacionamento é

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

Eu não testei, mas acho que isso também funcionaria

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