web-dev-qa-db-ja.com

SqlAlchemy-関係属性によるフィルタリング

SQLAlchemyの経験があまりなく、問題がありますが、解決できません。検索してみましたが、たくさんのコードを試しました。これは私のクラスです(最も重要なコードに縮小):

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)

母親のフェノスコアが(たとえば)== 10

言われたように、私は多くのコードを試しましたが、私はそれを得ません。私の目には、論理的な解決策は

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

なぜなら、あなたは.mother.phenoscore出力時の各要素に対してですが、このコードはそれを行いません。

リレーションシップの属性で(SQLステートメントを記述せずに、または追加の結合ステートメントを使用せずに)フィルターする(直接)可能性がある場合、この種類のフィルターが複数回必要です。

簡単な解決策がなくても、私はすべての答えをうれしく思います。

79
user1105851

リレーションシップのメソッド has() を使用します(読みやすい):

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

または参加(通常は高速):

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

結合を使用して関係を照会する必要があります

これから例を取得します 自己参照クエリ戦略

11
Nilesh

良いニュース:最近、「魔法の」文字列でフィルタリング/ソートできるパッケージを作成しました Djangoの場合 なので、次のように書くことができます

Patient.where(mother___phenoscore=10)

特に複雑なフィルターの場合は、はるかに短くなります。たとえば、

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

このパッケージをお楽しみください

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

セッションで使用しましたが、関係フィールドに直接アクセスできる別の方法は

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

私はそれをテストしていませんが、これもうまくいくと思います

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