SQLAlchemy:测试关系是否存在而不实际加载它
SQLAlchemy: Test if a relationship exists without actually loading it
我不确定这是否可行,但我在使用 SQLAlchemy 的 SQLite 中有一个层次结构。
在我的层次结构中,我想向用户指示 parent 具有 children,而无需加载所有 children。
我知道 SQLAlchemy 使用延迟加载,但是当我访问关系属性时,整个列表都被加载了。由于 parent 可以有数千个 children,这对于仅测试 children != None
.
来说是相当大的性能开销
目前关系定义如下:
children = relationship('child',
cascade='all',
backref=backref('parent'),
)
我目前测试 children 使用:
qry = session.query(parenttable).all()
for parent in qry:
if parent.children != None:
childrenindication = [{'Name': '...'}]
else:
childrenindication = []
hierarchylist.append({
'Name': parent.name,
'Children': childrenindication
})
如果有一种性能更友好的方式来做到这一点,那就太好了。
假设样本模型:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
children = relationship("Child", cascade="all", backref="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
parent_id = Column(ForeignKey(Parent.id))
下面列出了几个选项,其中第一个是对您问题的最直接回答:
选项 1:使用 Relationship.any(...) - 可能是最快的
has_children = Parent.children.any()
q = session.query(Parent, has_children)
for parent, has_children in q.all():
print(parent, has_children)
option-2:使用子查询
获取children的数量
# @note: returns None instead of 0 for parent with no children
from sqlalchemy import func
subq = (
session.query(Child.parent_id, func.count(Child.id).label("num_children"))
.group_by(Child.parent_id)
.subquery()
)
q = (session
.query(Parent, subq.c.num_children)
.outerjoin(subq, Parent.id == subq.c.parent_id)
)
for parent, has_children in q.all():
print(parent, has_children)
option-3:获取 children 没有 sub-query 的数量(如果 parent table 有
# not have many columns
from sqlalchemy import func
q = (session
.query(Parent, func.count(Child.id).label("num_children"))
.outerjoin(Child, Parent.children)
.group_by(Parent)
)
for parent, has_children in q.all():
print(parent, has_children)
我不确定这是否可行,但我在使用 SQLAlchemy 的 SQLite 中有一个层次结构。
在我的层次结构中,我想向用户指示 parent 具有 children,而无需加载所有 children。
我知道 SQLAlchemy 使用延迟加载,但是当我访问关系属性时,整个列表都被加载了。由于 parent 可以有数千个 children,这对于仅测试 children != None
.
目前关系定义如下:
children = relationship('child',
cascade='all',
backref=backref('parent'),
)
我目前测试 children 使用:
qry = session.query(parenttable).all()
for parent in qry:
if parent.children != None:
childrenindication = [{'Name': '...'}]
else:
childrenindication = []
hierarchylist.append({
'Name': parent.name,
'Children': childrenindication
})
如果有一种性能更友好的方式来做到这一点,那就太好了。
假设样本模型:
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
children = relationship("Child", cascade="all", backref="parent")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
parent_id = Column(ForeignKey(Parent.id))
下面列出了几个选项,其中第一个是对您问题的最直接回答:
选项 1:使用 Relationship.any(...) - 可能是最快的
has_children = Parent.children.any()
q = session.query(Parent, has_children)
for parent, has_children in q.all():
print(parent, has_children)
option-2:使用子查询
获取children的数量# @note: returns None instead of 0 for parent with no children
from sqlalchemy import func
subq = (
session.query(Child.parent_id, func.count(Child.id).label("num_children"))
.group_by(Child.parent_id)
.subquery()
)
q = (session
.query(Parent, subq.c.num_children)
.outerjoin(subq, Parent.id == subq.c.parent_id)
)
for parent, has_children in q.all():
print(parent, has_children)
option-3:获取 children 没有 sub-query 的数量(如果 parent table 有
# not have many columns
from sqlalchemy import func
q = (session
.query(Parent, func.count(Child.id).label("num_children"))
.outerjoin(Child, Parent.children)
.group_by(Parent)
)
for parent, has_children in q.all():
print(parent, has_children)