2011-12-19 18 views
49

No tengo mucha experiencia con SQLAlchemy y un problema, que no puedo resolver sino buscar un código que intenta mucho. Esta es mi clase (reducido a un código más significativo):SqlAlchemy - Filtrando por relación Atributo

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) 

y me gustaría para consultar todos los pacientes, cuya madre phenoscore es (por ejemplo) == 10

Según lo dicho, he intentado un montón de código, pero no lo entiendo La solución lógicamente, en mi opinión, sería

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

debido, puede acceder a .mother.phenoscore para cada elemento, pero cuando se da salida, este código no lo hace. Existe la posibilidad (directa) de filtrar por un atributo de una relación (sin escribir la declaración SQL, o una declaración de combinación adicional), necesito este tipo de filtro más de una vez.

Aunque no existe una solución fácil, estoy feliz por todas las respuestas

muchas gracias Christo

Respuesta

88

uso método has() de la relación (más legible):

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

o unirse (por lo general más rápido):

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

pacientes Patient.query.filter (Patient.mother.has (Patient.phenoscore == 1 0)) – user1105851

+0

@ user1105851 'has()' admite tanto la expresión de la condición como el argumento sin nombre y los argumentos de la palabra clave 'filter_by'-style. El último me parece más legible. –

+0

@DenisOtkidach correcto, pero entonces sería 'phenoscore = 10'. 'filter_by' solo toma palabras clave de igualdad (ya que solo está haciendo ** kwargs en ellas) – aruisdante

2

Buenas noticias para usted: I paquete recién hecho que le da el filtrado/clasificación con cuerdas "mágicas" as in Django, lo que ahora puede escribir algo como

Patient.where(mother___phenoscore=10) 

es mucho más corto, especialmente para filtros complejos, por ejemplo,

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

Ho Pé podrá disfrutar de este paquete de

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

1

Lo utilicé con sesiones, pero de manera alternativa en la que se puede acceder al campo de relación es directamente

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

Yo no lo he probado, pero supongo esto también funcionaría

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