混合属性表达式:一对多的多边聚合属性
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了混合属性表达式:一对多的多边聚合属性相关的知识,希望对你有一定的参考价值。
假设这些模型:
class A(Base):
...
targets = relationship("B", back_populates='a')
...
class B(Base):
...
a_id = Column(Integer, ForeignKey('a.id'))
a = relationship("A", back_populates='targets')
attr = Column(ENUM('a', 'b', 'c', name='options'), default='a')
...
我怎么能写一个hybrid_attribute.expression
为所有A
s返回True,其中任何相关的B
s在attr
中有('b', 'c')
属性值? (如果没有相关的B
s,这也应该返回False。)
这让我走到了一半:
# hybrid_attribute expression in A model
@example_attr.expression
def example_attr(cls):
return case(
[
(
B.attr.in_(('b','c')),
True
)
],
else_=False
)
但是接下来我如何通过qazxswpoi对它们进行分组,如果有任何相关的A.id
s是B
那么True
列的example_attr
列值是A
?
我希望能够做到:True
编辑1:
这个SQL似乎提供了所需的结果:
session.query(A).filter(A.example_attr.is_(True)).all()
但是我在引用子查询中的别名字段时遇到了一个小问题:
select a.id, coalesce(bool_or(a_id_b_attr.status), false)
from a left outer join (
select b.a_id as a_id, b.attr in ('b', 'c') as status from b
) as a_id_b_attr
on a.id = a_id_b_attr.a_id group by a.id;
这引发了sub = db.session.query(B.a_id.label('a_id'), B.attr.in_(('b', 'c')).label('status')).subquery()
db.session.query(
A.id,
db.func.coalesce(
db.func.bool_or(sub.status),
False
)
).
outerjoin(sub, A.id == sub.key_id).
group_by(A.id)
看到AttribubteError
没有任何别名归因。
我怎么能写一个
sub
来为所有人返回hybrid_attribute.expression
哪里有任何相关的B在True
中有一个attr属性值? (如果没有相关的B,这也应该返回('b', 'c')
。)
您可以使用EXISTS子查询表达式:
False
这不依赖于任何分组,而是依赖,并且可以直接在您想要的查询中使用:
class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)
targets = relationship("B", back_populates='a')
@hybrid_property
def example_attr(self):
return any(b.attr in {'b', 'c'} for b in self.targets)
@example_attr.expression
def example_attr(cls):
return exists().
where(and_(B.a_id == cls.id,
B.attr.in_(['b', 'c']))).
correlate(cls)
class B(Base):
__tablename__ = 'b'
id = Column(Integer, primary_key=True)
a_id = Column(Integer, ForeignKey('a.id'))
a = relationship("A", back_populates='targets')
attr = Column(ENUM('a', 'b', 'c', name='options'), default='a')
Postgresql能够使用相关的EXISTS子查询表达式重写(某些)查询到# Note that comparing booleans with booleans is a bit redundant
session.query(A).filter(A.example_attr).all()
,因此关于相关性的通常性能注释可能不适用。
如果你想使用分组来处理这个问题,你可以使用semijoins和显式连接:
bool_or
Postgresql允许在此分组查询中选择session.query(A).
join(B).
group_by(A.id).
having(func.bool_or(B.attr.in_(['b', 'c']))).
all()
的所有列,即使它们不是聚合表达式,因为它们在功能上依赖于分组列 - 换句话说,A
确定所选列。
以上是关于混合属性表达式:一对多的多边聚合属性的主要内容,如果未能解决你的问题,请参考以下文章
iOS核心数据如何使用NSPredicate根据一对多的子属性查找父对象?
DDD 在一个聚合中的实体之间以一对多而不是一对多的聚合边界