[英]SqlAlchemy - Filtering by Relationship Attribute
I don't have much experience with SQLAlchemy and I have a problem, which I can't solve.我对 SQLAlchemy 没有太多经验,而且我遇到了一个无法解决的问题。 I tried searching and I tried a lot of code.
我尝试搜索并尝试了很多代码。 This is my Class (reduced to the most significant code):
这是我的课程(简化为最重要的代码):
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)
and I would like to query all patients, whose mother's phenoscore is (for example) == 10
我想查询所有患者,其母亲的 phenoscore 是(例如)
== 10
As told, I tried a lot of code, but I don't get it.如前所述,我尝试了很多代码,但我不明白。 The logically solution, in my eyes, would be
在我看来,合乎逻辑的解决方案是
patients = Patient.query.filter(Patient.mother.phenoscore == 10)
because, you can access .mother.phenoscore
for each element when outputting but, this code doesn't do it.因为,您可以在输出时访问每个元素的
.mother.phenoscore
,但是这段代码并没有这样做。
Is there a (direct) possibility to filter by an attribute of a relationship (without writing the SQL Statement, or an extra join-statement), I need this kind of filter more than one time.是否有(直接)可能通过关系的属性进行过滤(无需编写 SQL 语句或额外的连接语句),我需要这种过滤器不止一次。
Even if there is no easy solution, I am happy to get all answers.即使没有简单的解决方案,我也很高兴得到所有答案。
You have to query the relationsip with join你必须用join查询relationship
You will get the example from this Self-Referential Query Strategies您将从这个自引用查询策略中获得示例
Good news for you: I recently made package that gives you filtering/sorting with "magical" strings as in Django , so you can now write something like给你的好消息:我最近制作了一个包,可以像在 Django 中一样使用“神奇”的字符串进行过滤/排序,因此你现在可以编写类似
Patient.where(mother___phenoscore=10)
It's a lot shorter, especially for complex filters, say,它要短得多,尤其是对于复杂的过滤器,例如,
Comment.where(post___public=True, post___user___name__like='Bi%')
Hope you will enjoy this package希望你会喜欢这个包
https://github.com/absent1706/sqlalchemy-mixins#django-like-queries https://github.com/absent1706/sqlalchemy-mixins#django-like-queries
I used it with sessions, but an alternate way where you can access the relationship field directly is我将它与会话一起使用,但是您可以直接访问关系字段的另一种方法是
db_session.query(Patient).join(Patient.mother) \
.filter(Patient.mother.property.mapper.class_.phenoscore==10)
I have not tested it, but I guess this would also work我还没有测试过,但我想这也行
Patient.query.join(Patient.mother) \
.filter(Patient.mother.property.mapper.class_.phenoscore==10)
This is a more general answer on how to query relationships.这是关于如何查询关系的更一般的答案。
relationship(..., lazy='dynamic', ...)
This allows you to:这允许您:
parent_obj.some_relationship.filter(ParentClass.some_attr==True).all()
For those looking to accomplish this filter using a declarative base, you can use an association proxy :对于那些希望使用声明性基础来完成此过滤器的人,您可以使用关联代理:
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')
Instead of using has()
on the relationship, you can query the child directly:您可以直接查询孩子,而不是在关系上使用
has()
:
patients = Patient.query.filter(Patient.mother_phenoscore == 10)
I use 'any()' function for add filter query on relationship column.我使用 '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)
Use like this像这样使用
articles = ArticleModel.query.filter(ArticleModel.tags.any(tag_id=tag_id)).all()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.