如何在Django中高效地递归查询?

2024-10-02 04:31:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个模型,看起来像:

class StaffMember(models.Model):

    id = models.OneToOneField(to=User, unique=True, primary_key=True, related_name='staff_member')
    supervisor = models.ForeignKey(to='self', null=True, blank=True, related_name='team_members')

我当前团队的层次结构是这样设计的,比如说有一个管理员(他在层次结构的最顶端)。现在,假设有3个人(A,B,C)向管理员报告,A、B和C中的每个人都有自己的团队向他们报告,以此类推。在

我要为任何员工查找所有团队成员(向下滚动到最底层的层级)。 我目前获取一个人所有团队成员的方法如下:

^{pr2}$

我通过以下方式获取成员的团队成员:

member = StaffMember.objects.get(pk=72)
team = member.get_team()

但是很明显,这会导致大量的db调用,而我的API最终会超时。有什么方法能更有效地吸引团队中的所有成员?在


Tags: to方法nametrueget层次结构models管理员
2条回答

如果您使用的数据库支持递归公共表表达式(例如PostgreSQL),这正是用例。在

team = StaffMember.objects.raw('''
    WITH RECURSIVE team(id, supervisor) AS (
          SELECT id, supervisor 
          FROM staff_member
          WHERE id = 42
        UNION ALL
          SELECT sm.id, sm.supervisor
          FROM staff_member AS sm, team AS t
          WHERE sm.id = t.supervisor
        )
    SELECT * FROM team
''')

参考文献: Raw SQL queries in Django
Recursive Common Table Expressions in PostgreSQL

我找到了解决问题的办法。递归解决方案获取节点,转到它的第一个子节点,并深入到层次结构的底部。然后再次回到第二个子对象(如果存在),然后再次向下直到底部。简言之,它逐个探索所有节点,并将所有成员追加到一个数组中。我想出的解决方案是分层获取成员。在

member = StaffMember.objects.get(id__id=user_id)

new_list = [member]

new_list = get_final_team(new_list)

def get_final_team(qs):
    team = []
    staffmembers = StaffMember.objects.filter(supervisor__in=qs)

    team += staffmembers 
    if staffmembers:
        interim_team_qs = get_final_team(staffmembers)
        for qs in interim_team_qs:
            team.append(qs)
    else:
        team = [qs]

    return team

此方法所需的db调用数是指在我们要查找其团队的成员下面存在的(层次结构的)层数。在

相关问题 更多 >

    热门问题