簡體   English   中英

SqlAlchemy - 按關系屬性過濾

[英]SqlAlchemy - Filtering by Relationship Attribute

我對 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)

我想查詢所有患者,其母親的 phenoscore 是(例如) == 10

如前所述,我嘗試了很多代碼,但我不明白。 在我看來,合乎邏輯的解決方案是

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

因為,您可以在輸出時訪問每個元素的.mother.phenoscore ,但是這段代碼並沒有這樣做。

是否有(直接)可能通過關系的屬性進行過濾(無需編寫 SQL 語句或額外的連接語句),我需要這種過濾器不止一次。

即使沒有簡單的解決方案,我也很高興得到所有答案。

使用關系的has()方法(更具可讀性):

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

或加入(通常更快):

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

你必須用join查詢relationship

您將從這個自引用查詢策略中獲得示例

給你的好消息:我最近制作了一個包,可以像在 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)

這是關於如何查詢關系的更一般的答案。

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM