我有由外键链接的多级一对多表。
我经常根据family_id、祖父母和父母的名字来查询特定的孩子
查询结果应该只有一个。
如果一个子记录不存在,我将创建一个新的子记录并将其链接到给定的父记录。
-
子表的数目比父表的数目大得多。
儿童>gt>gt;家长>gt;祖父母>系列
-
来自不同家庭的人可以有相同的名字。
(子表中的名称可以相同,因为它们可能来自不同的家庭和不同的父母(
以下是的模型定义
class Families:
__tablename__ = 'families'
id = Column(Integer, primary_key=True)
family_name = Column(String, nullable=False)
grand_parents = relationship(GrandParents, backref="family")
class GrandParents:
__tablename__ = 'grand_parents'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
family_id = Column(Integer, ForeignKey("families.id"))
parents = relationship(Parents, backref="grand_parent")
class Parents:
__tablename__ = 'parents'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
grand_parent_id = Column(Integer, ForeignKey("grand_parents.id"))
childs = relationship(Childs, backref="parent")
class Childs:
__tablename__ = 'childs'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False)
parent_id = Column(Integer, ForeignKey("parents.id"))
现在,我使用join通过给定的family_id、祖父母的名字和父母的名字来查询目标子行
def get_child(family_id, grand_praent_name, parent_name, child_name):
child = session.query(Childs)
.join(Parents)
.join(GrandParents)
.filter(GrandParents.family_id == family_id,
GrandParents.name == grand_praent_name,
Parents.name == parent_name,
Childs.name == child_name).one_or_none()
return child
但每次,我都必须进行这种查询(遍历特定家族的所有子代,并根据业务逻辑更新它们的值(。
是否有更好的方法/设计/惯用方法来进行这种查询
如果只更新child
,那么查询看起来不错。您可以考虑使用with_entities
来避免获取许多不必要的数据:
def get_child(family_id, grand_praent_name, parent_name, child_name):
child = session.query(Childs)
.join(Parents)
.join(GrandParents)
.filter(GrandParents.family_id == family_id,
GrandParents.name == grand_praent_name,
Parents.name == parent_name,
Childs.name == child_name)
.with_entities(Childs).one_or_none()
return child
如果要同时更新parent
或grandparent
,则应使用joinedload
以避免其他隐式查询。
如果您的查询遇到性能问题,您应该向外键添加索引以改进连接,例如:
parent_id = Column(Integer, ForeignKey("parents.id"), index=True)