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


93

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

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)

そして、私はすべての患者を照会したいと思います。 == 10

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

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

.mother.phenoscore出力時に各要素にアクセスできますが、このコードではアクセスできないためです。

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

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

回答:


167

has()関係の使用方法(より読みやすい):

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

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

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

9
患者= Patient.query.filter(Patient.mother.has(Patient.phenoscore == 10))
user1105851

@ user1105851 has()は、名前のない引数としての条件式と-style filter_byキーワード引数の両方をサポートしています。後者の方が読みやすいようです。
Denis Otkidach 2011

@DenisOtkidachは正しいですが、そうなりますphenoscore = 10filter_by平等キーワードのみを取ります(それは**クワーグを実行しているため)
aruisdante

@aruisdanteそうですね、答えの誤編集でした。
Denis Otkidach 14

4
代わりにanyを使用します。患者= Patient.query.filter(Patient.mother.any(phenoscore = 10))
Boston


7

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

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)

5

あなたに朗報: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


0

これは、関係を照会する方法に関するより一般的な答えです。

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

これにより、次のことが可能になります。

parent_obj.some_relationship.filter(ParentClass.some_attr==True).all()
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.