programing

SqlAlchemy - 관계 속성별 필터링

lastmoon 2023. 7. 21. 21:52
반응형

SqlAlchemy - 관계 속성별 필터링

저는 SQL 화학에 대한 경험이 많지 않고 해결할 수 없는 문제가 있습니다.저는 검색을 시도했고 많은 코드를 시도했습니다.내 클래스입니다(가장 중요한 코드로 축소됨).

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 문 또는 추가 조인 문을 작성하지 않고) 관계의 속성으로 필터링할 수 있는 (직접) 가능성이 있습니까? 이런 종류의 필터가 두 번 이상 필요합니다.

쉬운 해결책이 없더라도 모든 답을 얻을 수 있어 기쁩니다.

관계 방법 사용(가독성 향상):

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

또는 조인(일반적으로 더 빠름):

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

조인과 관련된 관계를 쿼리해야 합니다.

자체 참조 쿼리 전략에서 예제를 얻을 수 있습니다.

좋은 소식입니다: 저는 최근에 장고에서처럼 "마법적인" 문자열로 필터링/정렬을 제공하는 패키지를 만들었습니다. 그래서 이제 당신은 다음과 같은 것을 쓸 수 있습니다.

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)

이것은 관계를 쿼리하는 방법에 대한 보다 일반적인 답변입니다.

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

이를 통해 다음을 수행할 수 있습니다.

parent_obj.some_relationship.filter(ParentClass.some_attr==True).all()

선언 기반을 사용하여 이 필터를 수행하려는 사용자는 연결 프록시를 사용할 수 있습니다.

from sqlalchemy.ext.associationproxy import association_proxy

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)

    """
    Access the associated object(s) through this proxy
    
    Note: Because the above relationship doesn't use a
      collection (uselist=False), the associated attribute
      will be a scalar. If the relationship does use a
      collection (uselist=True), the associated attribute 
      would then be a list (or other defined collection) of values.
    """
    mother_phenoscore = association_proxy('mother', 'phenoscore')

사용하는 대신has()관계에서 하위 항목을 직접 쿼리할 수 있습니다.

patients = Patient.query.filter(Patient.mother_phenoscore == 10)

관계 열에 필터 쿼리를 추가하려면 'any()' 함수를 사용합니다.

class ArticleModel(db.Model, BaseModel):
__tablename__ = "articles"

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(120), nullable=False)
thumbnail = db.Column(db.String(240), nullable=True)
short_content = db.Column(db.String(400), nullable=False)
content = db.Column(db.String, nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey("categories.id"), nullable=False)
category = db.relationship("CategoryModel", backref="articles", lazy=True)
views_count = db.Column(db.Integer, default=0, nullable=False)
comment_count = db.Column(db.Integer, default=0, nullable=False)
comments = db.relationship("CommentModel", backref="articles")
tags = db.relationship("ArticleTagModel", backref="articles", lazy=True)
seo_tags = db.Column(db.String(150), default="Software, Flask, Python, .Net Core, Web, Developer, JavaScript, React, Asp.Net, HTML5, CSS3, Web Development, Mobile, React Native", nullable=False)
seo_description = db.Column(db.String(150), default="", nullable=False)


class ArticleTagModel(db.Model, BaseModel):
__tablename__ = "article_tags"

id = db.Column(db.Integer, primary_key=True, autoincrement=True)
article_id = db.Column(db.Integer, db.ForeignKey("articles.id"), nullable=False)
tag_id = db.Column(db.Integer, db.ForeignKey("tags.id"), nullable=False)
tag = db.relationship("TagModel", backref="article_tags", lazy=True)

이렇게 사용

articles = ArticleModel.query.filter(ArticleModel.tags.any(tag_id=tag_id)).all()

언급URL : https://stackoverflow.com/questions/8561470/sqlalchemy-filtering-by-relationship-attribute

반응형